diff options
Diffstat (limited to 'include/clang/Lex')
-rw-r--r-- | include/clang/Lex/DirectoryLookup.h | 34 | ||||
-rw-r--r-- | include/clang/Lex/ExternalPreprocessorSource.h | 4 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 30 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearchOptions.h | 67 | ||||
-rw-r--r-- | include/clang/Lex/Lexer.h | 50 | ||||
-rw-r--r-- | include/clang/Lex/LiteralSupport.h | 8 | ||||
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 471 | ||||
-rw-r--r-- | include/clang/Lex/ModuleLoader.h | 41 | ||||
-rw-r--r-- | include/clang/Lex/ModuleMap.h | 55 | ||||
-rw-r--r-- | include/clang/Lex/PPCallbacks.h | 66 | ||||
-rw-r--r-- | include/clang/Lex/PPConditionalDirectiveRecord.h | 102 | ||||
-rw-r--r-- | include/clang/Lex/PPMutationListener.h | 43 | ||||
-rw-r--r-- | include/clang/Lex/PTHManager.h | 6 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 97 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 184 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessorOptions.h | 52 | ||||
-rw-r--r-- | include/clang/Lex/Token.h | 12 |
17 files changed, 863 insertions, 459 deletions
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index d773fc6..261dfab 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -50,34 +50,34 @@ private: /// SrcMgr::CharacteristicKind. unsigned DirCharacteristic : 2; - /// UserSupplied - True if this is a user-supplied directory. - /// - bool UserSupplied : 1; - /// LookupType - This indicates whether this DirectoryLookup object is a /// normal directory, a framework, or a headermap. unsigned LookupType : 2; /// \brief Whether this is a header map used when building a framework. unsigned IsIndexHeaderMap : 1; + + /// \brief Whether we've performed an exhaustive search for module maps + /// within the subdirectories of this directory. + unsigned SearchedAllModuleMaps : 1; public: /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'dir'. DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT, - bool isUser, bool isFramework) - : DirCharacteristic(DT), UserSupplied(isUser), + bool isFramework) + : DirCharacteristic(DT), LookupType(isFramework ? LT_Framework : LT_NormalDir), - IsIndexHeaderMap(false) { + IsIndexHeaderMap(false), SearchedAllModuleMaps(false) { u.Dir = dir; } /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'map'. DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT, - bool isUser, bool isIndexHeaderMap) - : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap), - IsIndexHeaderMap(isIndexHeaderMap) { + bool isIndexHeaderMap) + : DirCharacteristic(DT), LookupType(LT_HeaderMap), + IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) { u.Map = map; } @@ -113,16 +113,22 @@ public: /// isHeaderMap - Return true if this is a header map, not a normal directory. bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; } + /// \brief Determine whether we have already searched this entire + /// directory for module maps. + bool haveSearchedAllModuleMaps() const { return SearchedAllModuleMaps; } + + /// \brief Specify whether we have already searched all of the subdirectories + /// for module maps. + void setSearchedAllModuleMaps(bool SAMM) { + SearchedAllModuleMaps = SAMM; + } + /// DirCharacteristic - The type of directory this is, one of the DirType enum /// values. SrcMgr::CharacteristicKind getDirCharacteristic() const { return (SrcMgr::CharacteristicKind)DirCharacteristic; } - /// isUserSupplied - True if this is a user-supplied directory. - /// - bool isUserSupplied() const { return UserSupplied; } - /// \brief Whether this header map is building a framework or not. bool isIndexHeaderMap() const { return isHeaderMap() && IsIndexHeaderMap; diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index d2e2412..d9a4de4 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -15,7 +15,9 @@ #define LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H namespace clang { - + +class IdentifierInfo; + /// \brief Abstract interface for external sources of preprocessor /// information. /// diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 4334db7..8a5a798 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -18,10 +18,10 @@ #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" -#include "llvm/ADT/OwningPtr.h" #include <vector> namespace clang { @@ -50,6 +50,9 @@ struct HeaderFileInfo { /// \brief Whether this header file info was supplied by an external source. unsigned External : 1; + + /// \brief Whether this header is part of a module. + unsigned isModuleHeader : 1; /// \brief Whether this structure is considered to already have been /// "resolved", meaning that it was loaded from the external source. @@ -90,7 +93,8 @@ struct HeaderFileInfo { HeaderFileInfo() : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), - External(false), Resolved(false), IndexHeaderMapHeader(false), + External(false), isModuleHeader(false), Resolved(false), + IndexHeaderMapHeader(false), NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {} /// \brief Retrieve the controlling macro for this header file, if @@ -134,7 +138,7 @@ class HeaderSearch { }; /// \brief Header-search options used to initialize this header search. - llvm::IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts; + IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts; FileManager &FileMgr; /// \#include search path information. Requests for \#include "x" search the @@ -189,7 +193,7 @@ class HeaderSearch { std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps; /// \brief The mapping between modules and headers. - ModuleMap ModMap; + mutable ModuleMap ModMap; /// \brief Describes whether a given directory has a module map in it. llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap; @@ -217,7 +221,7 @@ class HeaderSearch { friend class DirectoryLookup; public: - HeaderSearch(llvm::IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, + HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, FileManager &FM, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target); ~HeaderSearch(); @@ -363,7 +367,8 @@ public: StringRef Filename, const FileEntry *RelativeFileEnt, SmallVectorImpl<char> *SearchPath, - SmallVectorImpl<char> *RelativePath); + SmallVectorImpl<char> *RelativePath, + Module **SuggestedModule); /// \brief Look up the specified framework name in our framework cache. /// \returns The DirectoryEntry it is in if we know, null otherwise. @@ -399,6 +404,9 @@ public: getFileInfo(File).DirInfo = SrcMgr::C_System; } + /// \brief Mark the specified file as part of a module. + void MarkFileModuleHeader(const FileEntry *File); + /// \brief Increment the count for the number of times the specified /// FileEntry has been entered. void IncrementIncludeCount(const FileEntry *File) { @@ -468,7 +476,7 @@ public: /// \brief Retrieve the module that corresponds to the given file, if any. /// /// \param File The header that we wish to map to a module. - Module *findModuleForHeader(const FileEntry *File); + Module *findModuleForHeader(const FileEntry *File) const; /// \brief Read the contents of the given module map file. /// @@ -480,7 +488,7 @@ public: /// \brief Collect the set of all known, top-level modules. /// /// \param Modules Will be filled with the set of known, top-level modules. - void collectAllModules(llvm::SmallVectorImpl<Module *> &Modules); + void collectAllModules(SmallVectorImpl<Module *> &Modules); private: /// \brief Retrieve a module with the given name, which may be part of the @@ -497,7 +505,11 @@ private: Module *loadFrameworkModule(StringRef Name, const DirectoryEntry *Dir, bool IsSystem); - + + /// \brief Load all of the module maps within the immediate subdirectories + /// of the given search directory. + void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir); + public: /// \brief Retrieve the module map. ModuleMap &getModuleMap() { return ModMap; } diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index 468fefa..afce5ba 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -10,8 +10,11 @@ #ifndef LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H #define LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H +#include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringRef.h" +#include <string> #include <vector> namespace clang { @@ -27,6 +30,8 @@ namespace frontend { 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. @@ -37,12 +42,11 @@ namespace frontend { /// HeaderSearchOptions - Helper class for storing options related to the /// initialization of the HeaderSearch object. -class HeaderSearchOptions : public llvm::RefCountedBase<HeaderSearchOptions> { +class HeaderSearchOptions : public RefCountedBase<HeaderSearchOptions> { public: struct Entry { std::string Path; frontend::IncludeDirGroup Group; - unsigned IsUserSupplied : 1; unsigned IsFramework : 1; /// IgnoreSysRoot - This is false if an absolute path should be treated @@ -50,24 +54,10 @@ public: /// path. unsigned IgnoreSysRoot : 1; - /// \brief True if this entry is an internal search path. - /// - /// This typically indicates that users didn't directly provide it, but - /// instead it was provided by a compatibility layer for a particular - /// system. This isn't redundant with IsUserSupplied (even though perhaps - /// it should be) because that is false for user provided '-iwithprefix' - /// header search entries. - unsigned IsInternal : 1; - - /// \brief True if this entry's headers should be wrapped in extern "C". - unsigned ImplicitExternC : 1; - - Entry(StringRef path, frontend::IncludeDirGroup group, - bool isUserSupplied, bool isFramework, bool ignoreSysRoot, - bool isInternal, bool implicitExternC) - : Path(path), Group(group), IsUserSupplied(isUserSupplied), - IsFramework(isFramework), IgnoreSysRoot(ignoreSysRoot), - IsInternal(isInternal), ImplicitExternC(implicitExternC) {} + Entry(StringRef path, frontend::IncludeDirGroup group, bool isFramework, + bool ignoreSysRoot) + : Path(path), Group(group), IsFramework(isFramework), + IgnoreSysRoot(ignoreSysRoot) {} }; struct SystemHeaderPrefix { @@ -98,13 +88,35 @@ public: /// \brief The directory used for the module cache. std::string ModuleCachePath; - + /// \brief Whether we should disable the use of the hash string within the /// module cache. /// /// Note: Only used for testing! unsigned DisableModuleHash : 1; - + + /// \brief The interval (in seconds) between pruning operations. + /// + /// This operation is expensive, because it requires Clang to walk through + /// the directory structure of the module cache, stat()'ing and removing + /// files. + /// + /// The default value is large, e.g., the operation runs once a week. + unsigned ModuleCachePruneInterval; + + /// \brief The time (in seconds) after which an unused module file will be + /// considered unused and will, therefore, be pruned. + /// + /// When the module cache is pruned, any module file that has not been + /// 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; + + /// \brief The set of macro names that should be ignored for the purposes + /// of computing the module hash. + llvm::SetVector<std::string> ModulesIgnoreMacros; + /// Include the compiler builtin includes. unsigned UseBuiltinIncludes : 1; @@ -122,16 +134,17 @@ public: public: HeaderSearchOptions(StringRef _Sysroot = "/") - : Sysroot(_Sysroot), DisableModuleHash(0), UseBuiltinIncludes(true), + : Sysroot(_Sysroot), DisableModuleHash(0), + ModuleCachePruneInterval(7*24*60*60), + ModuleCachePruneAfter(31*24*60*60), + UseBuiltinIncludes(true), UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false) {} /// AddPath - Add the \p Path path to the specified \p Group list. void AddPath(StringRef Path, frontend::IncludeDirGroup Group, - bool IsUserSupplied, bool IsFramework, bool IgnoreSysRoot, - bool IsInternal = false, bool ImplicitExternC = false) { - UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, - IgnoreSysRoot, IsInternal, ImplicitExternC)); + bool IsFramework, bool IgnoreSysRoot) { + UserEntries.push_back(Entry(Path, Group, IsFramework, IgnoreSysRoot)); } /// AddSystemHeaderPrefix - Override whether \#include directives naming a diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 407b644..cb4f57f 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -14,11 +14,11 @@ #ifndef LLVM_CLANG_LEXER_H #define LLVM_CLANG_LEXER_H -#include "clang/Lex/PreprocessorLexer.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/PreprocessorLexer.h" #include "llvm/ADT/SmallVector.h" -#include <string> #include <cassert> +#include <string> namespace clang { class DiagnosticsEngine; @@ -174,8 +174,8 @@ public: /// SetKeepWhitespaceMode - This method lets clients enable or disable /// whitespace retention mode. void SetKeepWhitespaceMode(bool Val) { - assert((!Val || LexingRawMode) && - "Can only enable whitespace retention in raw mode"); + assert((!Val || LexingRawMode || LangOpts.TraditionalCPP) && + "Can only retain whitespace in raw mode or -traditional-cpp"); ExtendedTokenMode = Val ? 2 : 0; } @@ -194,6 +194,14 @@ public: ExtendedTokenMode = Mode ? 1 : 0; } + /// Sets the extended token mode back to its initial value, according to the + /// language options and preprocessor. This controls whether the lexer + /// produces comment and whitespace tokens. + /// + /// This requires the lexer to have an associated preprocessor. A standalone + /// lexer has nothing to reset to. + void resetExtendedTokenMode(); + const char *getBufferStart() const { return BufferStart; } /// ReadToEndOfLine - Read the rest of the current preprocessor line as an @@ -260,10 +268,10 @@ public: /// location and does not jump to the expansion or spelling /// location. static StringRef getSpelling(SourceLocation loc, - SmallVectorImpl<char> &buffer, - const SourceManager &SourceMgr, - const LangOptions &LangOpts, - bool *invalid = 0); + SmallVectorImpl<char> &buffer, + const SourceManager &SourceMgr, + const LangOptions &LangOpts, + bool *invalid = 0); /// 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. @@ -273,6 +281,12 @@ public: const SourceManager &SM, const LangOptions &LangOpts); + /// \brief Relex the token at the specified location. + /// \returns true if there was a failure, false on success. + static bool getRawToken(SourceLocation Loc, Token &Result, + const SourceManager &SM, + const LangOptions &LangOpts); + /// \brief Given a location any where in a source buffer, find the location /// that corresponds to the beginning of the token in which the original /// source location lands. @@ -431,6 +445,11 @@ private: /// void LexTokenInternal(Token &Result); + /// Given that a token begins with the Unicode character \p C, figure out + /// what kind of token it is and dispatch to the appropriate lexing helper + /// function. + void LexUnicode(Token &Result, uint32_t C, const char *CurPtr); + /// FormTokenWithChars - When we lex a token, we have identified a span /// starting at BufferPtr, going to TokEnd that forms the token. This method /// takes that range and assigns it to the token as its location and size. In @@ -573,6 +592,21 @@ private: void cutOffLexing() { BufferPtr = BufferEnd; } bool isHexaLiteral(const char *Start, const LangOptions &LangOpts); + + + /// Read a universal character name. + /// + /// \param CurPtr The position in the source buffer after the initial '\'. + /// If the UCN is syntactically well-formed (but not necessarily + /// 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 + /// and handle token formation in the caller. + /// + /// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is + /// invalid. + uint32_t tryReadUCN(const char *&CurPtr, const char *SlashLoc, Token *Tok); }; diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 3b68d1b..b1430cc 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -15,13 +15,13 @@ #ifndef CLANG_LITERALSUPPORT_H #define CLANG_LITERALSUPPORT_H +#include "clang/Basic/CharInfo.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/TokenKinds.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" -#include "clang/Basic/TokenKinds.h" -#include <cctype> namespace clang { @@ -101,7 +101,7 @@ private: /// SkipHexDigits - Read and skip over any hex digits, up to End. /// Return a pointer to the first non-hex digit or End. const char *SkipHexDigits(const char *ptr) { - while (ptr != ThisTokEnd && isxdigit(*ptr)) + while (ptr != ThisTokEnd && isHexDigit(*ptr)) ptr++; return ptr; } @@ -117,7 +117,7 @@ private: /// SkipDigits - Read and skip over any digits, up to End. /// Return a pointer to the first non-hex digit or End. const char *SkipDigits(const char *ptr) { - while (ptr != ThisTokEnd && isdigit(*ptr)) + while (ptr != ThisTokEnd && isDigit(*ptr)) ptr++; return ptr; } diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index aba77d5..64323b7 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the MacroInfo interface. -// +/// +/// \file +/// \brief Defines the clang::MacroInfo and clang::MacroDirective classes. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_MACROINFO_H @@ -22,34 +23,28 @@ namespace clang { class Preprocessor; -/// MacroInfo - Each identifier that is \#define'd has an instance of this class -/// associated with it, used to implement macro expansion. +/// \brief Encapsulates the data about a macro definition (e.g. its tokens). +/// +/// There's an instance of this class for every #define. class MacroInfo { //===--------------------------------------------------------------------===// // State set when the macro is defined. - /// Location - This is the place the macro is defined. + /// \brief The location the macro is defined. SourceLocation Location; - /// EndLocation - The location of the last token in the macro. + /// \brief The location of the last token in the macro. SourceLocation EndLocation; - /// \brief The location where the macro was #undef'd, or an invalid location - /// for macros that haven't been undefined. - SourceLocation UndefLocation; - /// \brief Previous definition, the identifier of this macro was defined to, - /// or NULL. - MacroInfo *PreviousDefinition; - /// Arguments - The list of arguments for a function-like macro. This can be - /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this + /// \brief The list of arguments for a function-like macro. + /// + /// ArgumentList points to the first of NumArguments pointers. + /// + /// 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 **ArgumentList; - unsigned NumArguments; - /// \brief The location at which this macro was either explicitly exported - /// from its module or marked as private. - /// - /// If invalid, this macro has not been explicitly given any visibility. - SourceLocation VisibilityLocation; + /// \see ArgumentList + unsigned NumArguments; /// \brief This is the list of tokens that the macro is defined to. SmallVector<Token, 8> ReplacementTokens; @@ -58,119 +53,88 @@ class MacroInfo { mutable unsigned DefinitionLength; mutable bool IsDefinitionLengthCached : 1; - /// \brief True if this macro is a function-like macro, false if it - /// is an object-like macro. + /// \brief True if this macro is function-like, false if it is object-like. bool IsFunctionLike : 1; - /// IsC99Varargs - True if this macro is of the form "#define X(...)" or - /// "#define X(Y,Z,...)". The __VA_ARGS__ token should be replaced with the - /// contents of "..." in an invocation. + /// \brief True if this macro is of the form "#define X(...)" or + /// "#define X(Y,Z,...)". + /// + /// The __VA_ARGS__ token should be replaced with the contents of "..." in an + /// invocation. bool IsC99Varargs : 1; - /// IsGNUVarargs - True if this macro is of the form "#define X(a...)". The - /// "a" identifier in the replacement list will be replaced with all arguments + /// \brief True if this macro is of the form "#define X(a...)". + /// + /// The "a" identifier in the replacement list will be replaced with all arguments /// of the macro starting with the specified one. bool IsGNUVarargs : 1; - /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if - /// it has not yet been redefined or undefined. + /// \brief True if this macro requires processing before expansion. + /// + /// This is the case for builtin macros such as __LINE__, so long as they have + /// not been redefined, but not for regular predefined macros from the "<built-in>" + /// memory buffer (see Preprocessing::getPredefinesFileID). bool IsBuiltinMacro : 1; - /// \brief True if this macro was loaded from an AST file. - bool IsFromAST : 1; - - /// \brief Whether this macro changed after it was loaded from an AST file. - bool ChangedAfterLoad : 1; + /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__" + bool HasCommaPasting : 1; private: //===--------------------------------------------------------------------===// // State that changes as the macro is used. - /// IsDisabled - True if we have started an expansion of this macro already. + /// \brief True if we have started an expansion of this macro already. + /// /// This disables recursive expansion, which would be quite bad for things /// like \#define A A. bool IsDisabled : 1; - /// IsUsed - True if this macro is either defined in the main file and has - /// been used, or if it is not defined in the main file. This is used to - /// emit -Wunused-macros diagnostics. + /// \brief True if this macro is either defined in the main file and has + /// been used, or if it is not defined in the main file. + /// + /// This is used to emit -Wunused-macros diagnostics. bool IsUsed : 1; - /// AllowRedefinitionsWithoutWarning - True if this macro can be redefined - /// without emitting a warning. + /// \brief True if this macro can be redefined without emitting a warning. bool IsAllowRedefinitionsWithoutWarning : 1; /// \brief Must warn if the macro is unused at the end of translation unit. bool IsWarnIfUnused : 1; - - /// \brief Whether the macro has public (when described in a module). - bool IsPublic : 1; - /// \brief Whether the macro definition is currently "hidden". - /// Note that this is transient state that is never serialized to the AST - /// file. - bool IsHidden : 1; + /// \brief Whether this macro info was loaded from an AST file. + unsigned FromASTFile : 1; - /// \brief Whether the definition of this macro is ambiguous, due to - /// multiple definitions coming in from multiple modules. - bool IsAmbiguous : 1; - - ~MacroInfo() { + ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); } public: MacroInfo(SourceLocation DefLoc); - MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator); - /// FreeArgumentList - Free the argument list of the macro, restoring it to a - /// state where it can be reused for other devious purposes. + /// \brief Free the argument list of the macro. + /// + /// This restores this MacroInfo to a state where it can be reused for other + /// devious purposes. void FreeArgumentList() { ArgumentList = 0; NumArguments = 0; } - /// Destroy - destroy this MacroInfo object. + /// \brief Destroy this MacroInfo object. void Destroy() { FreeArgumentList(); this->~MacroInfo(); } - /// getDefinitionLoc - Return the location that the macro was defined at. - /// + /// \brief Return the location that the macro was defined at. SourceLocation getDefinitionLoc() const { return Location; } - /// setDefinitionEndLoc - Set the location of the last token in the macro. - /// + /// \brief Set the location of the last token in the macro. void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; } - /// getDefinitionEndLoc - Return the location of the last token in the macro. - /// + /// \brief Return the location of the last token in the macro. SourceLocation getDefinitionEndLoc() const { return EndLocation; } - /// \brief Set the location where macro was undefined. Can only be set once. - void setUndefLoc(SourceLocation UndefLoc) { - assert(UndefLocation.isInvalid() && "UndefLocation is already set!"); - assert(UndefLoc.isValid() && "Invalid UndefLoc!"); - UndefLocation = UndefLoc; - } - - /// \brief Get the location where macro was undefined. - SourceLocation getUndefLoc() const { return UndefLocation; } - - /// \brief Set previous definition of the macro with the same name. - void setPreviousDefinition(MacroInfo *PreviousDef) { - PreviousDefinition = PreviousDef; - } - - /// \brief Get previous definition of the macro with the same name. - MacroInfo *getPreviousDefinition() { return PreviousDefinition; } - - /// \brief Find macro definition active in the specified source location. If - /// this macro was not defined there, return NULL. - const MacroInfo *findDefinitionAtLoc(SourceLocation L, - SourceManager &SM) const; - /// \brief Get length in characters of the macro definition. unsigned getDefinitionLength(SourceManager &SM) const { if (IsDefinitionLengthCached) @@ -178,25 +142,27 @@ public: return getDefinitionLengthSlow(SM); } - /// isIdenticalTo - Return true if the specified macro definition is equal to - /// this macro in spelling, arguments, and whitespace. This is used to emit - /// duplicate definition warnings. This implements the rules in C99 6.10.3. - bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const; - - /// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag. + /// \brief Return true if the specified macro definition is equal to + /// this macro in spelling, arguments, and whitespace. /// + /// \param Syntactically if true, the macro definitions can be identical even + /// if they use different identifiers for the function macro parameters. + /// Otherwise the comparison is lexical and this implements the rules in + /// C99 6.10.3. + bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, + bool Syntactically) const; + + /// \brief Set or clear the isBuiltinMacro flag. void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; } - /// setIsUsed - Set the value of the IsUsed flag. - /// + /// \brief Set the value of the IsUsed flag. void setIsUsed(bool Val) { IsUsed = Val; } - /// setIsAllowRedefinitionsWithoutWarning - Set the value of the - /// IsAllowRedefinitionsWithoutWarning flag. + /// \brief Set the value of the IsAllowRedefinitionsWithoutWarning flag. void setIsAllowRedefinitionsWithoutWarning(bool Val) { IsAllowRedefinitionsWithoutWarning = Val; } @@ -206,8 +172,8 @@ public: IsWarnIfUnused = val; } - /// setArgumentList - Set the specified list of identifiers as the argument - /// list for this macro. + /// \brief Set the specified list of identifiers as the argument list for + /// this macro. void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs, llvm::BumpPtrAllocator &PPAllocator) { assert(ArgumentList == 0 && NumArguments == 0 && @@ -228,7 +194,7 @@ public: arg_iterator arg_end() const { return ArgumentList+NumArguments; } unsigned getNumArgs() const { return NumArguments; } - /// getArgumentNum - Return the argument number of the specified identifier, + /// \brief Return the argument number of the specified identifier, /// or -1 if the identifier is not a formal argument identifier. int getArgumentNum(IdentifierInfo *Arg) const { for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I) @@ -249,30 +215,22 @@ public: bool isGNUVarargs() const { return IsGNUVarargs; } bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; } - /// isBuiltinMacro - Return true if this macro is a builtin macro, such as - /// __LINE__, which requires processing before expansion. + /// \brief Return true if this macro requires processing before expansion. + /// + /// This is true only for builtin macro, such as \__LINE__, whose values + /// are not given by fixed textual expansions. Regular predefined macros + /// from the "<built-in>" buffer are not reported as builtins by this + /// function. bool isBuiltinMacro() const { return IsBuiltinMacro; } - /// isFromAST - Return true if this macro was loaded from an AST file. - bool isFromAST() const { return IsFromAST; } - - /// setIsFromAST - Set whether this macro was loaded from an AST file. - void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; } + bool hasCommaPasting() const { return HasCommaPasting; } + void setHasCommaPasting() { HasCommaPasting = true; } - /// \brief Determine whether this macro has changed since it was loaded from - /// an AST file. - bool hasChangedAfterLoad() const { return ChangedAfterLoad; } - - /// \brief Note whether this macro has changed after it was loaded from an - /// AST file. - void setChangedAfterLoad(bool CAL = true) { ChangedAfterLoad = CAL; } - - /// isUsed - Return false if this macro is defined in the main file and has + /// \brief Return false if this macro is defined in the main file and has /// not yet been used. bool isUsed() const { return IsUsed; } - /// isAllowRedefinitionsWithoutWarning - Return true if this macro can be - /// redefined without warning. + /// \brief Return true if this macro can be redefined without warning. bool isAllowRedefinitionsWithoutWarning() const { return IsAllowRedefinitionsWithoutWarning; } @@ -282,7 +240,7 @@ public: return IsWarnIfUnused; } - /// getNumTokens - Return the number of tokens that this macro expands to. + /// \brief Return the number of tokens that this macro expands to. /// unsigned getNumTokens() const { return ReplacementTokens.size(); @@ -298,16 +256,16 @@ public: tokens_iterator tokens_end() const { return ReplacementTokens.end(); } bool tokens_empty() const { return ReplacementTokens.empty(); } - /// AddTokenToBody - Add the specified token to the replacement text for the - /// macro. + /// \brief Add the specified token to the replacement text for the macro. void AddTokenToBody(const Token &Tok) { assert(!IsDefinitionLengthCached && "Changing replacement tokens after definition length got calculated"); ReplacementTokens.push_back(Tok); } - /// isEnabled - Return true if this macro is enabled: in other words, that we - /// are not currently in an expansion of this macro. + /// \brief Return true if this macro is enabled. + /// + /// In other words, that we are not currently in an expansion of this macro. bool isEnabled() const { return !IsDisabled; } void EnableMacro() { @@ -320,41 +278,272 @@ public: IsDisabled = true; } - /// \brief Set the export location for this macro. - void setVisibility(bool Public, SourceLocation Loc) { - VisibilityLocation = Loc; - IsPublic = Public; + /// \brief Determine whether this macro info came from an AST file (such as + /// a precompiled header or module) rather than having been parsed. + bool isFromASTFile() const { return FromASTFile; } + + /// \brief Retrieve the global ID of the module that owns this particular + /// macro info. + unsigned getOwningModuleID() const { + if (isFromASTFile()) + return *(const unsigned*)(this+1); + + return 0; } - /// \brief Determine whether this macro is part of the public API of its - /// module. - bool isPublic() const { return IsPublic; } - - /// \brief Determine the location where this macro was explicitly made - /// public or private within its module. - SourceLocation getVisibilityLocation() { return VisibilityLocation; } +private: + unsigned getDefinitionLengthSlow(SourceManager &SM) const; + + void setOwningModuleID(unsigned ID) { + assert(isFromASTFile()); + *(unsigned*)(this+1) = ID; + } + + friend class Preprocessor; +}; + +class DefMacroDirective; + +/// \brief Encapsulates changes to the "macros namespace" (the location where +/// the macro name became active, the location where it was undefined, etc.). +/// +/// MacroDirectives, associated with an identifier, are used to model the macro +/// history. Usually a macro definition (MacroInfo) is where a macro name +/// becomes active (MacroDirective) but modules can have their own macro +/// history, separate from the local (current translation unit) macro history. +/// +/// For example, if "@import A;" imports macro FOO, there will be a new local +/// MacroDirective created to indicate that "FOO" became active at the import +/// location. Module "A" itself will contain another MacroDirective in its macro +/// history (at the point of the definition of FOO) and both MacroDirectives +/// will point to the same MacroInfo object. +/// +class MacroDirective { +public: + enum Kind { + MD_Define, + MD_Undefine, + MD_Visibility + }; + +protected: + /// \brief Previous macro directive for the same identifier, or NULL. + MacroDirective *Previous; + + SourceLocation Loc; + + /// \brief MacroDirective kind. + unsigned MDKind : 2; + + /// \brief True if the macro directive was loaded from a PCH file. + bool IsFromPCH : 1; - /// \brief Determine whether this macro is currently defined (and has not - /// been #undef'd) or has been hidden. - bool isDefined() const { return UndefLocation.isInvalid() && !IsHidden; } + /// \brief Whether the macro directive is currently "hidden". + /// + /// Note that this is transient state that is never serialized to the AST + /// file. + bool IsHidden : 1; + + // Used by DefMacroDirective -----------------------------------------------// - /// \brief Determine whether this macro definition is hidden. + /// \brief True if this macro was imported from a module. + bool IsImported : 1; + + /// \brief Whether the definition of this macro is ambiguous, due to + /// multiple definitions coming in from multiple modules. + bool IsAmbiguous : 1; + + // Used by VisibilityMacroDirective ----------------------------------------// + + /// \brief Whether the macro has public visibility (when described in a + /// module). + bool IsPublic : 1; + + MacroDirective(Kind K, SourceLocation Loc) + : Previous(0), Loc(Loc), MDKind(K), IsFromPCH(false), IsHidden(false), + IsImported(false), IsAmbiguous(false), + IsPublic(true) { + } + +public: + Kind getKind() const { return Kind(MDKind); } + + SourceLocation getLocation() const { return Loc; } + + /// \brief Set previous definition of the macro with the same name. + void setPrevious(MacroDirective *Prev) { + Previous = Prev; + } + + /// \brief Get previous definition of the macro with the same name. + const MacroDirective *getPrevious() const { return Previous; } + + /// \brief Get previous definition of the macro with the same name. + MacroDirective *getPrevious() { return Previous; } + + /// \brief Return true if the macro directive was loaded from a PCH file. + bool isFromPCH() const { return IsFromPCH; } + + void setIsFromPCH() { IsFromPCH = true; } + + /// \brief Determine whether this macro directive is hidden. bool isHidden() const { return IsHidden; } - /// \brief Set whether this macro definition is hidden. + /// \brief Set whether this macro directive is hidden. void setHidden(bool Val) { IsHidden = Val; } + class DefInfo { + DefMacroDirective *DefDirective; + SourceLocation UndefLoc; + bool IsPublic; + + public: + DefInfo() : DefDirective(0) { } + + DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc, + bool isPublic) + : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) { } + + const DefMacroDirective *getDirective() const { return DefDirective; } + DefMacroDirective *getDirective() { return DefDirective; } + + inline SourceLocation getLocation() const; + inline MacroInfo *getMacroInfo(); + const MacroInfo *getMacroInfo() const { + return const_cast<DefInfo*>(this)->getMacroInfo(); + } + + SourceLocation getUndefLocation() const { return UndefLoc; } + bool isUndefined() const { return UndefLoc.isValid(); } + + bool isPublic() const { return IsPublic; } + + bool isValid() const { return DefDirective != 0; } + bool isInvalid() const { return !isValid(); } + + operator bool() const { return isValid(); } + + inline DefInfo getPreviousDefinition(bool AllowHidden = false); + const DefInfo getPreviousDefinition(bool AllowHidden = false) const { + return const_cast<DefInfo*>(this)->getPreviousDefinition(AllowHidden); + } + }; + + /// \brief Traverses the macro directives history and returns the next + /// macro definition directive along with info about its undefined location + /// (if there is one) and if it is public or private. + DefInfo getDefinition(bool AllowHidden = false); + const DefInfo getDefinition(bool AllowHidden = false) const { + return const_cast<MacroDirective*>(this)->getDefinition(AllowHidden); + } + + bool isDefined(bool AllowHidden = false) const { + if (const DefInfo Def = getDefinition(AllowHidden)) + return !Def.isUndefined(); + return false; + } + + const MacroInfo *getMacroInfo(bool AllowHidden = false) const { + return getDefinition(AllowHidden).getMacroInfo(); + } + MacroInfo *getMacroInfo(bool AllowHidden = false) { + return getDefinition(AllowHidden).getMacroInfo(); + } + + /// \brief Find macro definition active in the specified source location. If + /// this macro was not defined there, return NULL. + const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const; + + static bool classof(const MacroDirective *) { return true; } +}; + +/// \brief A directive for a defined macro or a macro imported from a module. +class DefMacroDirective : public MacroDirective { + MacroInfo *Info; + +public: + explicit DefMacroDirective(MacroInfo *MI) + : MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) { + assert(MI && "MacroInfo is null"); + } + + DefMacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported) + : MacroDirective(MD_Define, Loc), Info(MI) { + assert(MI && "MacroInfo is null"); + IsImported = isImported; + } + + /// \brief The data for the macro definition. + const MacroInfo *getInfo() const { return Info; } + MacroInfo *getInfo() { return Info; } + + /// \brief True if this macro was imported from a module. + bool isImported() const { return IsImported; } + /// \brief Determine whether this macro definition is ambiguous with /// other macro definitions. bool isAmbiguous() const { return IsAmbiguous; } /// \brief Set whether this macro definition is ambiguous. void setAmbiguous(bool Val) { IsAmbiguous = Val; } - -private: - unsigned getDefinitionLengthSlow(SourceManager &SM) const; + + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Define; + } + static bool classof(const DefMacroDirective *) { return true; } +}; + +/// \brief A directive for an undefined macro. +class UndefMacroDirective : public MacroDirective { +public: + explicit UndefMacroDirective(SourceLocation UndefLoc) + : MacroDirective(MD_Undefine, UndefLoc) { + assert(UndefLoc.isValid() && "Invalid UndefLoc!"); + } + + static bool classof(const MacroDirective *MD) { + return MD->getKind() == MD_Undefine; + } + static bool classof(const UndefMacroDirective *) { return true; } +}; + +/// \brief A directive for setting the module visibility of a macro. +class VisibilityMacroDirective : public MacroDirective { +public: + explicit VisibilityMacroDirective(SourceLocation Loc, bool Public) + : MacroDirective(MD_Visibility, Loc) { + IsPublic = Public; + } + + /// \brief Determine whether this macro is part of the public API of its + /// module. + bool isPublic() const { return IsPublic; } + + 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 DefDirective->getLocation(); +} + +inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() { + if (isInvalid()) + return 0; + return DefDirective->getInfo(); +} + +inline MacroDirective::DefInfo +MacroDirective::DefInfo::getPreviousDefinition(bool AllowHidden) { + if (isInvalid() || DefDirective->getPrevious() == 0) + return DefInfo(); + return DefDirective->getPrevious()->getDefinition(AllowHidden); +} + } // end namespace clang #endif diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index 36d03c0..3acf915 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -17,16 +17,36 @@ #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerIntPair.h" namespace clang { class IdentifierInfo; - +class Module; + /// \brief A sequence of identifier/location pairs used to describe a particular /// module or submodule, e.g., std.vector. -typedef llvm::ArrayRef<std::pair<IdentifierInfo*, SourceLocation> > - ModuleIdPath; - +typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation> > ModuleIdPath; + +/// \brief Describes the result of attempting to load a module. +class ModuleLoadResult { + llvm::PointerIntPair<Module *, 1, bool> Storage; + +public: + ModuleLoadResult() : Storage() { } + + ModuleLoadResult(Module *module, bool missingExpected) + : Storage(module, missingExpected) { } + + operator Module *() const { return Storage.getPointer(); } + + /// \brief Determines whether the module, which failed to load, was + /// actually a submodule that we expected to see (based on implying the + /// submodule from header structure), but didn't materialize in the actual + /// module. + bool isMissingExpected() const { return Storage.getInt(); } +}; + /// \brief Abstract interface for a module loader. /// /// This abstract interface describes a module loader, which is responsible @@ -55,9 +75,16 @@ public: /// /// \returns If successful, returns the loaded module. Otherwise, returns /// NULL to indicate that the module could not be loaded. - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility, - bool IsInclusionDirective) = 0; + virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, + ModuleIdPath Path, + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) = 0; + + /// \brief Make the given module visible. + virtual void makeModuleVisible(Module *Mod, + Module::NameVisibilityKind Visibility, + SourceLocation ImportLoc, + bool Complain) = 0; }; } diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 082408d..1c9c673 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -22,8 +22,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include <string> namespace clang { @@ -33,6 +33,7 @@ class FileEntry; class FileManager; class DiagnosticConsumer; class DiagnosticsEngine; +class HeaderSearch; class ModuleMapParser; class ModuleMap { @@ -40,6 +41,7 @@ class ModuleMap { IntrusiveRefCntPtr<DiagnosticsEngine> Diags; const LangOptions &LangOpts; const TargetInfo *Target; + HeaderSearch &HeaderInfo; /// \brief The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". @@ -104,13 +106,17 @@ class ModuleMap { /// \brief The names of modules that cannot be inferred within this /// directory. - llvm::SmallVector<std::string, 2> ExcludedModules; + SmallVector<std::string, 2> ExcludedModules; }; /// \brief A mapping from directories to information about inferring /// framework modules from within those directories. llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories; + /// \brief Describes whether we haved parsed a particular file as a module + /// map. + llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap; + friend class ModuleMapParser; /// \brief Resolve the given export declaration into an actual export @@ -127,8 +133,21 @@ class ModuleMap { /// if the export could not be resolved. Module::ExportDecl resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, - bool Complain); - + bool Complain) const; + + /// \brief Resolve the given module id to an actual module. + /// + /// \param Id The module-id to resolve. + /// + /// \param Mod The module in which we're resolving the module-id. + /// + /// \param Complain Whether this routine should complain about unresolvable + /// module-ids. + /// + /// \returns The resolved module, or null if the module-id could not be + /// resolved. + Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const; + public: /// \brief Construct a new module map. /// @@ -143,7 +162,8 @@ public: /// /// \param Target The target for this translation unit. ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, - const LangOptions &LangOpts, const TargetInfo *Target); + const LangOptions &LangOpts, const TargetInfo *Target, + HeaderSearch &HeaderInfo); /// \brief Destroy the module map. /// @@ -157,6 +177,7 @@ public: void setBuiltinIncludeDir(const DirectoryEntry *Dir) { BuiltinIncludeDir = Dir; } + const DirectoryEntry *getBuiltinIncludeDir() { return BuiltinIncludeDir; } /// \brief Retrieve the module that owns the given header file, if any. /// @@ -168,14 +189,14 @@ public: /// \brief Determine whether the given header is part of a module /// marked 'unavailable'. - bool isHeaderInUnavailableModule(const FileEntry *Header); + bool isHeaderInUnavailableModule(const FileEntry *Header) const; /// \brief Retrieve a module with the given name. /// /// \param Name The name of the module to look up. /// /// \returns The named module, if known; otherwise, returns null. - Module *findModule(StringRef Name); + Module *findModule(StringRef Name) const; /// \brief Retrieve a module with the given name using lexical name lookup, /// starting at the given context. @@ -186,7 +207,7 @@ public: /// name lookup. /// /// \returns The named module, if known; otherwise, returns null. - Module *lookupModuleUnqualified(StringRef Name, Module *Context); + Module *lookupModuleUnqualified(StringRef Name, Module *Context) const; /// \brief Retrieve a module with the given name within the given context, /// using direct (qualified) name lookup. @@ -197,7 +218,7 @@ public: /// null, we will look for a top-level module. /// /// \returns The named submodule, if known; otherwose, returns null. - Module *lookupModuleQualified(StringRef Name, Module *Context); + Module *lookupModuleQualified(StringRef Name, Module *Context) const; /// \brief Find a new module or submodule, or create it if it does not already /// exist. @@ -231,7 +252,7 @@ public: /// \returns true if we are allowed to infer a framework module, and false /// otherwise. bool canInferFrameworkModule(const DirectoryEntry *ParentDir, - StringRef Name, bool &IsSystem); + StringRef Name, bool &IsSystem) const; /// \brief Infer the contents of a framework module map from the given /// framework directory. @@ -246,7 +267,7 @@ public: /// /// \returns The file entry for the module map file containing the given /// module, or NULL if the module definition was inferred. - const FileEntry *getContainingModuleMapFile(Module *Module); + const FileEntry *getContainingModuleMapFile(Module *Module) const; /// \brief Resolve all of the unresolved exports in the given module. /// @@ -258,7 +279,17 @@ public: /// false otherwise. bool resolveExports(Module *Mod, bool Complain); - /// \brief Infers the (sub)module based on the given source location and + /// \brief Resolve all of the unresolved conflicts in the given module. + /// + /// \param Mod The module whose conflicts should be resolved. + /// + /// \param Complain Whether to emit diagnostics for failures. + /// + /// \returns true if any errors were encountered while resolving conflicts, + /// false otherwise. + bool resolveConflicts(Module *Mod, bool Complain); + + /// \brief Infers the (sub)module based on the given source location and /// source manager. /// /// \param Loc The location within the source that we are querying, along diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 8ba02cc..96359a2 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -15,10 +15,10 @@ #ifndef LLVM_CLANG_LEX_PPCALLBACKS_H #define LLVM_CLANG_LEX_PPCALLBACKS_H +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleLoader.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/DiagnosticIDs.h" #include "llvm/ADT/StringRef.h" #include <string> @@ -26,7 +26,7 @@ namespace clang { class SourceLocation; class Token; class IdentifierInfo; - class MacroInfo; + class MacroDirective; /// \brief This interface provides a way to observe the actions of the /// preprocessor as it does its thing. @@ -184,22 +184,25 @@ public: /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a /// macro invocation is found. - virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, + virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, SourceRange Range) { } /// \brief Hook called whenever a macro definition is seen. - virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { + virtual void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever a macro \#undef is seen. /// - /// MI is released immediately following this callback. - virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { + /// MD is released immediately following this callback. + virtual void MacroUndefined(const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever the 'defined' operator is seen. - virtual void Defined(const Token &MacroNameTok) { + /// \param MD The MacroDirective if the name was a macro, null otherwise. + virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) { } /// \brief Hook called when a source range is skipped. @@ -228,13 +231,17 @@ public: /// \brief Hook called whenever an \#ifdef is seen. /// \param Loc the source location of the directive. /// \param MacroNameTok Information on the token being tested. - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { + /// \param MD The MacroDirective if the name was a macro, null otherwise. + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever an \#ifndef is seen. /// \param Loc the source location of the directive. /// \param MacroNameTok Information on the token being tested. - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { + /// \param MD The MacroDirective if the name was a macro, null otherwise. + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { } /// \brief Hook called whenever an \#else is seen. @@ -346,25 +353,26 @@ public: Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); } - virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, + virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, SourceRange Range) { - First->MacroExpands(MacroNameTok, MI, Range); - Second->MacroExpands(MacroNameTok, MI, Range); + First->MacroExpands(MacroNameTok, MD, Range); + Second->MacroExpands(MacroNameTok, MD, Range); } - virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { - First->MacroDefined(MacroNameTok, MI); - Second->MacroDefined(MacroNameTok, MI); + virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) { + First->MacroDefined(MacroNameTok, MD); + Second->MacroDefined(MacroNameTok, MD); } - virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { - First->MacroUndefined(MacroNameTok, MI); - Second->MacroUndefined(MacroNameTok, MI); + virtual void MacroUndefined(const Token &MacroNameTok, + const MacroDirective *MD) { + First->MacroUndefined(MacroNameTok, MD); + Second->MacroUndefined(MacroNameTok, MD); } - virtual void Defined(const Token &MacroNameTok) { - First->Defined(MacroNameTok); - Second->Defined(MacroNameTok); + virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD) { + First->Defined(MacroNameTok, MD); + Second->Defined(MacroNameTok, MD); } virtual void SourceRangeSkipped(SourceRange Range) { @@ -386,15 +394,17 @@ public: } /// \brief Hook called whenever an \#ifdef is seen. - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { - First->Ifdef(Loc, MacroNameTok); - Second->Ifdef(Loc, MacroNameTok); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { + First->Ifdef(Loc, MacroNameTok, MD); + Second->Ifdef(Loc, MacroNameTok, MD); } /// \brief Hook called whenever an \#ifndef is seen. - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { - First->Ifndef(Loc, MacroNameTok); - Second->Ifndef(Loc, MacroNameTok); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD) { + First->Ifndef(Loc, MacroNameTok, MD); + Second->Ifndef(Loc, MacroNameTok, MD); } /// \brief Hook called whenever an \#else is seen. diff --git a/include/clang/Lex/PPConditionalDirectiveRecord.h b/include/clang/Lex/PPConditionalDirectiveRecord.h new file mode 100644 index 0000000..b9a2252 --- /dev/null +++ b/include/clang/Lex/PPConditionalDirectiveRecord.h @@ -0,0 +1,102 @@ +//===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PPConditionalDirectiveRecord class, which maintains +// a record of conditional directive regions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H +#define LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/PPCallbacks.h" +#include "llvm/ADT/SmallVector.h" +#include <vector> + +namespace clang { + +/// \brief Records preprocessor conditional directive regions and allows +/// querying in which region source locations belong to. +class PPConditionalDirectiveRecord : public PPCallbacks { + SourceManager &SourceMgr; + + SmallVector<SourceLocation, 6> CondDirectiveStack; + + class CondDirectiveLoc { + SourceLocation Loc; + SourceLocation RegionLoc; + + public: + CondDirectiveLoc(SourceLocation Loc, SourceLocation RegionLoc) + : Loc(Loc), RegionLoc(RegionLoc) {} + + SourceLocation getLoc() const { return Loc; } + SourceLocation getRegionLoc() const { return RegionLoc; } + + class Comp { + SourceManager &SM; + public: + explicit Comp(SourceManager &SM) : SM(SM) {} + bool operator()(const CondDirectiveLoc &LHS, + const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc()); + } + bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) { + return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS); + } + bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) { + return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc()); + } + }; + }; + + typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; + /// \brief The locations of conditional directives in source order. + CondDirectiveLocsTy CondDirectiveLocs; + + void addCondDirectiveLoc(CondDirectiveLoc DirLoc); + +public: + /// \brief Construct a new preprocessing record. + explicit PPConditionalDirectiveRecord(SourceManager &SM); + + size_t getTotalMemory() const; + + SourceManager &getSourceManager() const { return SourceMgr; } + + /// \brief Returns true if the given range intersects with a conditional + /// directive. if a \#if/\#endif block is fully contained within the range, + /// this function will return false. + bool rangeIntersectsConditionalDirective(SourceRange Range) const; + + /// \brief Returns true if the given locations are in different regions, + /// separated by conditional directive blocks. + bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, + SourceLocation RHS) const { + return findConditionalDirectiveRegionLoc(LHS) != + findConditionalDirectiveRegionLoc(RHS); + } + + SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const; + +private: + virtual void If(SourceLocation Loc, SourceRange ConditionRange); + virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + virtual void Else(SourceLocation Loc, SourceLocation IfLoc); + virtual void Endif(SourceLocation Loc, SourceLocation IfLoc); +}; + +} // end namespace clang + +#endif // LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H diff --git a/include/clang/Lex/PPMutationListener.h b/include/clang/Lex/PPMutationListener.h deleted file mode 100644 index 5319c66..0000000 --- a/include/clang/Lex/PPMutationListener.h +++ /dev/null @@ -1,43 +0,0 @@ -//===--- PPMutationListener.h - Preprocessor Mutation Interface -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PPMutationListener interface. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H -#define LLVM_CLANG_LEX_PPTMUTATIONLISTENER_H - -#include "clang/Basic/SourceLocation.h" - -namespace clang { - -class MacroInfo; - -/// \brief A record that describes an update to a macro that was -/// originally loaded to an AST file and has been modified within the -/// current translation unit. -struct MacroUpdate { - /// \brief The source location at which this macro was #undef'd. - SourceLocation UndefLoc; -}; - -/// \brief An abstract interface that should be implemented by -/// listeners that want to be notified when a preprocessor entity gets -/// modified after its initial creation. -class PPMutationListener { -public: - virtual ~PPMutationListener(); - - /// \brief A macro has been #undef'd. - virtual void UndefinedMacro(MacroInfo *MI) { } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index e64dbd8..fad0806 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -14,10 +14,10 @@ #ifndef LLVM_CLANG_PTHMANAGER_H #define LLVM_CLANG_PTHMANAGER_H -#include "clang/Lex/PTHLexer.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Lex/PTHLexer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Allocator.h" #include <string> diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index 57e51b7..b13b2be 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -14,18 +14,19 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H #define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H -#include "clang/Lex/PPCallbacks.h" -#include "clang/Basic/SourceLocation.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/SmallVector.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include <vector> namespace clang { class IdentifierInfo; + class MacroInfo; class PreprocessingRecord; } @@ -277,9 +278,9 @@ namespace clang { /// \brief Optionally returns true or false if the preallocated preprocessed /// entity with index \p Index came from file \p FID. - virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, - FileID FID) { - return llvm::Optional<bool>(); + virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index, + FileID FID) { + return None; } }; @@ -303,44 +304,6 @@ namespace clang { /// and are referenced by the iterator using negative indices. std::vector<PreprocessedEntity *> LoadedPreprocessedEntities; - bool RecordCondDirectives; - unsigned CondDirectiveNextIdx; - SmallVector<unsigned, 6> CondDirectiveStack; - - class CondDirectiveLoc { - SourceLocation Loc; - unsigned Idx; - - public: - CondDirectiveLoc(SourceLocation Loc, unsigned Idx) : Loc(Loc), Idx(Idx) {} - - SourceLocation getLoc() const { return Loc; } - unsigned getIdx() const { return Idx; } - - class Comp { - SourceManager &SM; - public: - explicit Comp(SourceManager &SM) : SM(SM) {} - bool operator()(const CondDirectiveLoc &LHS, - const CondDirectiveLoc &RHS) { - return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc()); - } - bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) { - return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS); - } - bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) { - return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc()); - } - }; - }; - - typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; - /// \brief The locations of conditional directives in source order. - CondDirectiveLocsTy CondDirectiveLocs; - - void addCondDirectiveLoc(CondDirectiveLoc DirLoc); - unsigned findCondDirectiveIdx(SourceLocation Loc) const; - /// \brief Global (loaded or local) ID for a preprocessed entity. /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to @@ -363,7 +326,7 @@ namespace clang { } /// \brief Mapping from MacroInfo structures to their definitions. - llvm::DenseMap<const MacroInfo *, PPEntityID> MacroDefinitions; + llvm::DenseMap<const MacroInfo *, MacroDefinition *> MacroDefinitions; /// \brief External source of preprocessed entities. ExternalPreprocessingRecordSource *ExternalSource; @@ -394,11 +357,11 @@ namespace clang { unsigned allocateLoadedEntities(unsigned NumEntities); /// \brief Register a new macro definition. - void RegisterMacroDefinition(MacroInfo *Macro, PPEntityID PPID); + void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinition *Def); public: /// \brief Construct a new preprocessing record. - PreprocessingRecord(SourceManager &SM, bool RecordConditionalDirectives); + explicit PreprocessingRecord(SourceManager &SM); /// \brief Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { @@ -582,24 +545,6 @@ namespace clang { /// \brief Add a new preprocessed entity to this record. PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity); - /// \brief Returns true if this PreprocessingRecord is keeping track of - /// conditional directives locations. - bool isRecordingConditionalDirectives() const { - return RecordCondDirectives; - } - - /// \brief Returns true if the given range intersects with a conditional - /// directive. if a \#if/\#endif block is fully contained within the range, - /// this function will return false. - bool rangeIntersectsConditionalDirective(SourceRange Range) const; - - /// \brief Returns true if the given locations are in different regions, - /// separated by conditional directive blocks. - bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, - SourceLocation RHS) const { - return findCondDirectiveIdx(LHS) != findCondDirectiveIdx(RHS); - } - /// \brief Set the external source for preprocessed entities. void SetExternalSource(ExternalPreprocessingRecordSource &Source); @@ -613,10 +558,10 @@ namespace clang { MacroDefinition *findMacroDefinition(const MacroInfo *MI); private: - virtual void MacroExpands(const Token &Id, const MacroInfo* MI, + virtual void MacroExpands(const Token &Id, const MacroDirective *MD, SourceRange Range); - virtual void MacroDefined(const Token &Id, const MacroInfo *MI); - virtual void MacroUndefined(const Token &Id, const MacroInfo *MI); + virtual void MacroDefined(const Token &Id, const MacroDirective *MD); + virtual void MacroUndefined(const Token &Id, const MacroDirective *MD); virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, @@ -626,13 +571,15 @@ namespace clang { StringRef SearchPath, StringRef RelativePath, const Module *Imported); - virtual void If(SourceLocation Loc, SourceRange ConditionRange); - virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, - SourceLocation IfLoc); - virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok); - virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok); - virtual void Else(SourceLocation Loc, SourceLocation IfLoc); - virtual void Endif(SourceLocation Loc, SourceLocation IfLoc); + virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDirective *MD); + /// \brief Hook called whenever the 'defined' operator is seen. + virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD); + + void addMacroExpansion(const Token &Id, const MacroInfo *MI, + SourceRange Range); /// \brief Cached result of the last \see getPreprocessedEntitiesInRange /// query. diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index e9095fb..7a912ec 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -14,23 +14,22 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSOR_H #define LLVM_CLANG_LEX_PREPROCESSOR_H -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/Lexer.h" -#include "clang/Lex/PTHLexer.h" -#include "clang/Lex/PPCallbacks.h" -#include "clang/Lex/PPMutationListener.h" -#include "clang/Lex/TokenLexer.h" -#include "clang/Lex/PTHManager.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/PTHLexer.h" +#include "clang/Lex/PTHManager.h" +#include "clang/Lex/TokenLexer.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -84,7 +83,7 @@ public: /// like the \#include stack, token expansion, etc. /// class Preprocessor : public RefCountedBase<Preprocessor> { - llvm::IntrusiveRefCntPtr<PreprocessorOptions> PPOpts; + IntrusiveRefCntPtr<PreprocessorOptions> PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; const TargetInfo *Target; @@ -160,6 +159,12 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief True if pragmas are enabled. bool PragmasEnabled : 1; + /// \brief True if the current build action is a preprocessing action. + bool PreprocessedOutput : 1; + + /// \brief True if we are currently preprocessing a #if or #elif directive + bool ParsingIfOrElifDirective; + /// \brief True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; @@ -215,8 +220,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { SourceLocation ModuleImportLoc; /// \brief The module import path that we're currently processing. - llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> - ModuleImportPath; + SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath; /// \brief Whether the module import expectes an identifier next. Otherwise, /// it expects a '.' or ';'. @@ -291,24 +295,19 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// encountered (e.g. a file is \#included, etc). PPCallbacks *Callbacks; - /// \brief Listener whose actions are invoked when an entity in the - /// preprocessor (e.g., a macro) that was loaded from an AST file is - /// later mutated. - PPMutationListener *Listener; - struct MacroExpandsInfo { Token Tok; - MacroInfo *MI; + MacroDirective *MD; SourceRange Range; - MacroExpandsInfo(Token Tok, MacroInfo *MI, SourceRange Range) - : Tok(Tok), MI(MI), Range(Range) { } + MacroExpandsInfo(Token Tok, MacroDirective *MD, SourceRange Range) + : Tok(Tok), MD(MD), Range(Range) { } }; SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; /// Macros - For each IdentifierInfo that was associated with a macro, we /// keep a mapping to the history of all macro definitions and #undefs in /// the reverse order (the latest one is in the head of the list). - llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros; + llvm::DenseMap<const IdentifierInfo*, MacroDirective*> Macros; friend class ASTReader; /// \brief Macros that we want to warn because they are not used at the end @@ -343,6 +342,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// should use from the command line etc. std::string Predefines; + /// \brief The file ID for the preprocessor predefines. + FileID PredefinesFileID; + /// TokenLexerCache - Cache macro expanders to reduce malloc traffic. enum { TokenLexerCacheSize = 8 }; unsigned NumCachedTokenLexers; @@ -396,7 +398,7 @@ private: // Cached tokens state. MacroInfoChain *MICache; public: - Preprocessor(llvm::IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, + Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, @@ -447,6 +449,11 @@ public: /// \brief Retrieve the module loader associated with this preprocessor. ModuleLoader &getModuleLoader() const { return TheModuleLoader; } + /// \brief True if we are currently preprocessing a #if or #elif directive + bool isParsingIfOrElifDirective() const { + return ParsingIfOrElifDirective; + } + /// SetCommentRetentionState - Control whether or not the preprocessor retains /// comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { @@ -467,6 +474,16 @@ public: return SuppressIncludeNotFoundError; } + /// Sets whether the preprocessor is responsible for producing output or if + /// it is producing tokens to be consumed by Parse and Sema. + void setPreprocessedOutput(bool IsPreprocessedOutput) { + PreprocessedOutput = IsPreprocessedOutput; + } + + /// Returns true if the preprocessor is responsible for generating output, + /// false if it is producing tokens to be consumed by Parse and Sema. + bool isPreprocessedOutput() const { return PreprocessedOutput; } + /// isCurrentLexer - Return true if we are lexing directly from the specified /// lexer. bool isCurrentLexer(const PreprocessorLexer *L) const { @@ -483,6 +500,9 @@ public: /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; + /// \brief Returns the file ID for the preprocessor predefines. + FileID getPredefinesFileID() const { return PredefinesFileID; } + /// getPPCallbacks/addPPCallbacks - Accessors for preprocessor callbacks. /// Note that this class takes ownership of any PPCallbacks object given to /// it. @@ -493,53 +513,54 @@ public: Callbacks = C; } - /// \brief Attach an preprocessor mutation listener to the preprocessor. - /// - /// The preprocessor mutation listener provides the ability to track - /// modifications to the preprocessor entities committed after they were - /// initially created. - void setPPMutationListener(PPMutationListener *Listener) { - this->Listener = Listener; - } - - /// \brief Retrieve a pointer to the preprocessor mutation listener - /// associated with this preprocessor, if any. - PPMutationListener *getPPMutationListener() const { return Listener; } - - /// \brief Given an identifier, return the MacroInfo it is \#defined to - /// or null if it isn't \#define'd. - MacroInfo *getMacroInfo(IdentifierInfo *II) const { + /// \brief Given an identifier, return its latest MacroDirective if it is + // \#defined or null if it isn't \#define'd. + MacroDirective *getMacroDirective(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) return 0; - MacroInfo *MI = getMacroInfoHistory(II); - assert(MI->getUndefLoc().isInvalid() && "Macro is undefined!"); - return MI; + MacroDirective *MD = getMacroDirectiveHistory(II); + assert(MD->isDefined() && "Macro is undefined!"); + return MD; + } + + const MacroInfo *getMacroInfo(IdentifierInfo *II) const { + return const_cast<Preprocessor*>(this)->getMacroInfo(II); + } + + MacroInfo *getMacroInfo(IdentifierInfo *II) { + if (MacroDirective *MD = getMacroDirective(II)) + return MD->getMacroInfo(); + return 0; } /// \brief Given an identifier, return the (probably #undef'd) MacroInfo /// representing the most recent macro definition. One can iterate over all /// previous macro definitions from it. This method should only be called for /// identifiers that hadMacroDefinition(). - MacroInfo *getMacroInfoHistory(IdentifierInfo *II) const; - - /// \brief Specify a macro for this identifier. - void setMacroInfo(IdentifierInfo *II, MacroInfo *MI); - /// \brief Add a MacroInfo that was loaded from an AST file. - void addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI, - MacroInfo *Hint = 0); - /// \brief Make the given MacroInfo, that was loaded from an AST file and - /// previously hidden, visible. - void makeLoadedMacroInfoVisible(IdentifierInfo *II, MacroInfo *MI); - /// \brief Undefine a macro for this identifier. - void clearMacroInfo(IdentifierInfo *II); + MacroDirective *getMacroDirectiveHistory(const IdentifierInfo *II) const; + + /// \brief Add a directive to the macro directive history for this identifier. + void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD); + DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, + SourceLocation Loc, + bool isImported) { + DefMacroDirective *MD = AllocateDefMacroDirective(MI, Loc, isImported); + appendMacroDirective(II, MD); + return MD; + } + DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI){ + return appendDefMacroDirective(II, MI, MI->getDefinitionLoc(), false); + } + /// \brief Set a MacroDirective that was loaded from a PCH file. + void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD); /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro /// history table. Currently defined macros have /// IdentifierInfo::hasMacroDefinition() set and an empty /// MacroInfo::getUndefLoc() at the head of the list. - typedef llvm::DenseMap<IdentifierInfo*, - MacroInfo*>::const_iterator macro_iterator; + typedef llvm::DenseMap<const IdentifierInfo *, + MacroDirective*>::const_iterator macro_iterator; macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; @@ -611,7 +632,7 @@ public: /// \brief Create a new preprocessing record, which will keep track of /// all macro expansions, macro definitions, etc. - void createPreprocessingRecord(bool RecordConditionalDirectives); + void createPreprocessingRecord(); /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. @@ -696,6 +717,25 @@ public: void LexAfterModuleImport(Token &Result); + /// \brief Lex a string literal, which may be the concatenation of multiple + /// string literals and may even come from macro expansion. + /// \returns true on success, false if a error diagnostic has been generated. + bool LexStringLiteral(Token &Result, std::string &String, + const char *DiagnosticTag, bool AllowMacroExpansion) { + if (AllowMacroExpansion) + Lex(Result); + else + LexUnexpandedToken(Result); + return FinishLexStringLiteral(Result, String, DiagnosticTag, + AllowMacroExpansion); + } + + /// \brief Complete the lexing of a string literal where the first token has + /// already been lexed (see LexStringLiteral). + bool FinishLexStringLiteral(Token &Result, std::string &String, + const char *DiagnosticTag, + bool AllowMacroExpansion); + /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get /// something not a comment. This is useful in -E -C mode where comments /// would foul up preprocessor directive handling. @@ -901,8 +941,8 @@ public: /// "cleaning", e.g. if it contains trigraphs or escaped newlines /// \param invalid If non-null, will be set \c true if an error occurs. StringRef getSpelling(SourceLocation loc, - SmallVectorImpl<char> &buffer, - bool *invalid = 0) const { + SmallVectorImpl<char> &buffer, + bool *invalid = 0) const { return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid); } @@ -939,6 +979,12 @@ public: SmallVectorImpl<char> &Buffer, bool *Invalid = 0) const; + /// \brief Relex the token at the specified location. + /// \returns true if there was a failure, false on success. + bool getRawToken(SourceLocation Loc, Token &Result) { + return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts); + } + /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant /// with length 1, return the character. char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, @@ -1143,8 +1189,9 @@ public: /// \brief Allocate a new MacroInfo object with the provided SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); - /// \brief Allocate a new MacroInfo object which is clone of \p MI. - MacroInfo *CloneMacroInfo(const MacroInfo &MI); + /// \brief Allocate a new MacroInfo object loaded from an AST file. + MacroInfo *AllocateDeserializedMacroInfo(SourceLocation L, + unsigned SubModuleID); /// \brief Turn the specified lexer token into a fully checked and spelled /// filename, e.g. as an operand of \#include. @@ -1221,6 +1268,13 @@ private: /// \brief Allocate a new MacroInfo object. MacroInfo *AllocateMacroInfo(); + DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI, + SourceLocation Loc, + bool isImported); + UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc); + VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc, + bool isPublic); + /// \brief Release the specified MacroInfo for re-use. /// /// This memory will be reused for allocating new MacroInfo objects. @@ -1268,7 +1322,7 @@ private: /// HandleMacroExpandedIdentifier - If an identifier token is read that is to /// be expanded as a macro, handle it and return the next token as 'Tok'. If /// the macro should not be expanded return true, otherwise return false. - bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI); + bool HandleMacroExpandedIdentifier(Token &Tok, MacroDirective *MD); /// \brief Cache macro expanded tokens for TokenLexers. // @@ -1312,6 +1366,12 @@ private: /// start getting tokens from it using the PTH cache. void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir); + /// \brief Set the file ID for the preprocessor predefines. + void setPredefinesFileID(FileID FID) { + assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!"); + PredefinesFileID = FID; + } + /// IsFileLexer - Returns true if we are lexing from a file and not a /// pragma or a macro. static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) { @@ -1367,8 +1427,6 @@ private: // Macro handling. void HandleDefineDirective(Token &Tok); void HandleUndefDirective(Token &Tok); - void UndefineMacro(IdentifierInfo *II, MacroInfo *MI, - SourceLocation UndefLoc); // Conditional Inclusion. void HandleIfdefDirective(Token &Tok, bool isIfndef, diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index e5fe373..eba2a13 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -10,14 +10,16 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ #define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include <cassert> +#include <set> #include <string> #include <utility> #include <vector> -#include <set> namespace llvm { class MemoryBuffer; @@ -39,23 +41,20 @@ enum ObjCXXARCStandardLibraryKind { /// PreprocessorOptions - This class is used for passing the various options /// used in preprocessor initialization to InitializePreprocessor(). -class PreprocessorOptions : public llvm::RefCountedBase<PreprocessorOptions> { +class PreprocessorOptions : public RefCountedBase<PreprocessorOptions> { public: std::vector<std::pair<std::string, bool/*isUndef*/> > Macros; std::vector<std::string> Includes; std::vector<std::string> MacroIncludes; - unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler - /// and target specific predefines. + /// \brief Initialize the preprocessor with the compiler and target specific + /// predefines. + unsigned UsePredefines : 1; + + /// \brief Whether we should maintain a detailed record of all macro + /// definitions and expansions. + unsigned DetailedRecord : 1; - unsigned DetailedRecord : 1; /// Whether we should maintain a detailed - /// record of all macro definitions and - /// expansions. - unsigned DetailedRecordConditionalDirectives : 1; /// Whether in the - /// preprocessing record we should also keep - /// track of locations of conditional directives - /// in non-system files. - /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; @@ -119,14 +118,28 @@ public: /// with support for lifetime-qualified pointers. ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary; - /// \brief The path of modules being build, which is used to detect - /// cycles in the module dependency graph as modules are being built. - /// - /// There is no way to set this value from the command line. If we ever need - /// to do so (e.g., if on-demand module construction moves out-of-process), - /// we can add a cc1-level option to do so. - SmallVector<std::string, 2> ModuleBuildPath; + /// \brief Records the set of modules + class FailedModulesSet : public RefCountedBase<FailedModulesSet> { + llvm::StringSet<> Failed; + + public: + bool hasAlreadyFailed(StringRef module) { + return Failed.count(module) > 0; + } + + void addFailed(StringRef module) { + Failed.insert(module); + } + }; + /// \brief The set of modules that failed to build. + /// + /// This pointer will be shared among all of the compiler instances created + /// to (re)build modules, so that once a module fails to build anywhere, + /// other instances will see that the module has failed and won't try to + /// build it again. + IntrusiveRefCntPtr<FailedModulesSet> FailedModules; + typedef std::vector<std::pair<std::string, std::string> >::iterator remapped_file_iterator; typedef std::vector<std::pair<std::string, std::string> >::const_iterator @@ -163,7 +176,6 @@ public: public: PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DetailedRecordConditionalDirectives(false), DisablePCHValidation(false), AllowPCHWithCompilerErrors(false), DumpDeserializedPCHDecls(false), diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 50b86c8..bcbe9c9 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -14,10 +14,10 @@ #ifndef LLVM_CLANG_TOKEN_H #define LLVM_CLANG_TOKEN_H +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/OperatorKinds.h" #include <cstdlib> namespace clang { @@ -74,9 +74,10 @@ public: StartOfLine = 0x01, // At start of line or only after whitespace. LeadingSpace = 0x02, // Whitespace exists before this token. DisableExpand = 0x04, // This identifier may never be macro expanded. - NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. + NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. LeadingEmptyMacro = 0x10, // Empty macro exists before this token. - HasUDSuffix = 0x20 // This string or character literal has a ud-suffix. + HasUDSuffix = 0x20, // This string or character literal has a ud-suffix. + HasUCN = 0x40 // This identifier contains a UCN. }; tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } @@ -257,6 +258,9 @@ public: /// \brief Return true if this token is a string or character literal which /// has a ud-suffix. bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; } + + /// Returns true if this token contains a universal character name. + bool hasUCN() const { return (Flags & HasUCN) ? true : false; } }; /// \brief Information about the conditional stack (\#if directives) |