diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
| commit | 13cc256e404620c1de0cbcc4e43ce1e2dbbc4898 (patch) | |
| tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /include/clang/Lex | |
| parent | 657bc3d9848e3be92029b2416031340988cd0111 (diff) | |
Diffstat (limited to 'include/clang/Lex')
| -rw-r--r-- | include/clang/Lex/ExternalPreprocessorSource.h | 3 | ||||
| -rw-r--r-- | include/clang/Lex/HeaderMap.h | 5 | ||||
| -rw-r--r-- | include/clang/Lex/HeaderSearch.h | 25 | ||||
| -rw-r--r-- | include/clang/Lex/HeaderSearchOptions.h | 147 | ||||
| -rw-r--r-- | include/clang/Lex/Lexer.h | 91 | ||||
| -rw-r--r-- | include/clang/Lex/LiteralSupport.h | 10 | ||||
| -rw-r--r-- | include/clang/Lex/MacroInfo.h | 60 | ||||
| -rw-r--r-- | include/clang/Lex/ModuleMap.h | 74 | ||||
| -rw-r--r-- | include/clang/Lex/PPCallbacks.h | 53 | ||||
| -rw-r--r-- | include/clang/Lex/PPMutationListener.h | 43 | ||||
| -rw-r--r-- | include/clang/Lex/PTHLexer.h | 4 | ||||
| -rw-r--r-- | include/clang/Lex/PTHManager.h | 5 | ||||
| -rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 84 | ||||
| -rw-r--r-- | include/clang/Lex/Preprocessor.h | 128 | ||||
| -rw-r--r-- | include/clang/Lex/PreprocessorLexer.h | 4 | ||||
| -rw-r--r-- | include/clang/Lex/PreprocessorOptions.h | 221 | ||||
| -rw-r--r-- | include/clang/Lex/Token.h | 18 | ||||
| -rw-r--r-- | include/clang/Lex/TokenLexer.h | 17 |
18 files changed, 828 insertions, 164 deletions
diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index f172b5c8d22d..d2e2412192ed 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -28,9 +28,6 @@ public: /// \brief Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros() = 0; - /// \brief Read the definition for the given macro. - virtual void LoadMacroDefinition(IdentifierInfo *II) = 0; - /// \brief Update an out-of-date identifier. virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0; }; diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h index 107408dced10..8473a6a4e752 100644 --- a/include/clang/Lex/HeaderMap.h +++ b/include/clang/Lex/HeaderMap.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_LEX_HEADERMAP_H #include "clang/Basic/LLVM.h" +#include "llvm/Support/Compiler.h" namespace llvm { class MemoryBuffer; @@ -30,8 +31,8 @@ namespace clang { /// symlinks to files. Its advantages are that it is dense and more efficient /// to create and process than a directory of symlinks. class HeaderMap { - HeaderMap(const HeaderMap&); // DO NOT IMPLEMENT - void operator=(const HeaderMap&); // DO NOT IMPLEMENT + HeaderMap(const HeaderMap &) LLVM_DELETED_FUNCTION; + void operator=(const HeaderMap &) LLVM_DELETED_FUNCTION; const llvm::MemoryBuffer *FileBuffer; bool NeedsBSwap; diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 8e9491fdc339..4334db771c85 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -17,6 +17,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" @@ -29,6 +30,7 @@ class DiagnosticsEngine; class ExternalIdentifierLookup; class FileEntry; class FileManager; +class HeaderSearchOptions; class IdentifierInfo; /// \brief The preprocessor keeps track of this information for each @@ -131,8 +133,10 @@ class HeaderSearch { bool IsUserSpecifiedSystemFramework; }; + /// \brief Header-search options used to initialize this header search. + llvm::IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts; + FileManager &FileMgr; - DiagnosticsEngine &Diags; /// \#include search path information. Requests for \#include "x" search the /// directory of the \#including file first, then each directory in SearchDirs /// consecutively. Requests for <x> search the current dir first, then each @@ -207,17 +211,21 @@ class HeaderSearch { unsigned NumFrameworkLookups, NumSubFrameworkLookups; // HeaderSearch doesn't support default or copy construction. - explicit HeaderSearch(); - explicit HeaderSearch(const HeaderSearch&); - void operator=(const HeaderSearch&); - + HeaderSearch(const HeaderSearch&) LLVM_DELETED_FUNCTION; + void operator=(const HeaderSearch&) LLVM_DELETED_FUNCTION; + friend class DirectoryLookup; public: - HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags, + HeaderSearch(llvm::IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, + FileManager &FM, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target); ~HeaderSearch(); + /// \brief Retrieve the header-search options with which this header search + /// was initialized. + HeaderSearchOptions &getHeaderSearchOpts() const { return *HSOpts; } + FileManager &getFileMgr() const { return FileMgr; } /// \brief Interface for setting the file search paths. @@ -283,6 +291,11 @@ public: /// \brief Retrieve the path to the module cache. StringRef getModuleCachePath() const { return ModuleCachePath; } + + /// \brief Consider modules when including files from this directory. + void setDirectoryHasModuleMap(const DirectoryEntry* Dir) { + DirectoryHasModuleMap[Dir] = true; + } /// \brief Forget everything we know about headers so far. void ClearFileInfo() { diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h new file mode 100644 index 000000000000..468fefa4aba3 --- /dev/null +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -0,0 +1,147 @@ +//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H +#define LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace clang { + +namespace frontend { + /// IncludeDirGroup - Identifiers the group a include entry belongs to, which + /// represents its relative positive in the search list. A \#include of a "" + /// path starts at the -iquote group, then searches the Angled group, then + /// searches 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. + 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. + }; +} + +/// HeaderSearchOptions - Helper class for storing options related to the +/// initialization of the HeaderSearch object. +class HeaderSearchOptions : public llvm::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 + /// relative to the sysroot, or true if it should always be the absolute + /// 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) {} + }; + + struct SystemHeaderPrefix { + /// A prefix to be matched against paths in \#include directives. + std::string Prefix; + + /// True if paths beginning with this prefix should be treated as system + /// headers. + bool IsSystemHeader; + + SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) + : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} + }; + + /// If non-empty, the directory to use as a "virtual system root" for include + /// paths. + std::string Sysroot; + + /// User specified include entries. + std::vector<Entry> UserEntries; + + /// User-specified system header prefixes. + std::vector<SystemHeaderPrefix> SystemHeaderPrefixes; + + /// The directory which holds the compiler resource files (builtin includes, + /// etc.). + std::string ResourceDir; + + /// \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; + + /// Include the compiler builtin includes. + unsigned UseBuiltinIncludes : 1; + + /// Include the system standard include search directories. + unsigned UseStandardSystemIncludes : 1; + + /// Include the system standard C++ library include search directories. + unsigned UseStandardCXXIncludes : 1; + + /// Use libc++ instead of the default libstdc++. + unsigned UseLibcxx : 1; + + /// Whether header search information should be output as for -v. + unsigned Verbose : 1; + +public: + HeaderSearchOptions(StringRef _Sysroot = "/") + : Sysroot(_Sysroot), DisableModuleHash(0), 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)); + } + + /// AddSystemHeaderPrefix - Override whether \#include directives naming a + /// path starting with \p Prefix should be considered as naming a system + /// header. + void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { + SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader)); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index ca233de71c39..407b644fd74c 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -31,11 +31,11 @@ class DiagnosticBuilder; 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. + /// 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. + /// A Perforce-style conflict marker, initiated by 4 ">"s, + /// separated by 4 "="s, and terminated by 4 "<"s. CMK_Perforce }; @@ -83,8 +83,8 @@ class Lexer : public PreprocessorLexer { // CurrentConflictMarkerState - The kind of conflict marker we are handling. ConflictMarkerKind CurrentConflictMarkerState; - Lexer(const Lexer&); // DO NOT IMPLEMENT - void operator=(const Lexer&); // DO NOT IMPLEMENT + Lexer(const Lexer &) LLVM_DELETED_FUNCTION; + void operator=(const Lexer &) LLVM_DELETED_FUNCTION; friend class Preprocessor; void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd); @@ -128,9 +128,7 @@ public: SourceLocation getFileLoc() const { return FileLoc; } /// Lex - Return the next token in the file. If this is the end of file, it - /// return the tok::eof token. Return true if an error occurred and - /// compilation should terminate, false if normal. This implicitly involves - /// the preprocessor. + /// return the tok::eof token. This implicitly involves the preprocessor. void Lex(Token &Result) { // Start a new token. Result.startToken(); @@ -278,8 +276,6 @@ public: /// \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. - /// - /// \param Loc static SourceLocation GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts); @@ -324,7 +320,7 @@ public: /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. /// - /// \param MacroBegin If non-null and function returns true, it is set to + /// \param MacroEnd If non-null and function returns true, it is set to /// end location of the macro. static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, @@ -396,7 +392,36 @@ public: static std::pair<unsigned, bool> ComputePreamble(const llvm::MemoryBuffer *Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0); - + + /// \brief Checks that the given token is the first token that occurs after + /// the given location (this excludes comments and whitespace). Returns the + /// location immediately after the specified token. If the token is not found + /// or the location is inside a macro, the returned source location will be + /// invalid. + static SourceLocation findLocationAfterToken(SourceLocation loc, + tok::TokenKind TKind, + const SourceManager &SM, + const LangOptions &LangOpts, + bool SkipTrailingWhitespaceAndNewLine); + + /// \brief Returns true if the given character could appear in an identifier. + static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts); + + /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever + /// emit a warning. + static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, + const LangOptions &LangOpts) { + // If this is not a trigraph and not a UCN or escaped newline, return + // quickly. + if (isObviouslySimpleCharacter(Ptr[0])) { + Size = 1; + return *Ptr; + } + + Size = 0; + return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); + } + //===--------------------------------------------------------------------===// // Internal implementation interfaces. private: @@ -427,7 +452,6 @@ private: //===--------------------------------------------------------------------===// // Lexer character reading interfaces. -public: // This lexer is built on two interfaces for reading characters, both of which // automatically provide phase 1/2 translation. getAndAdvanceChar is used @@ -467,7 +491,6 @@ public: return C; } -private: /// ConsumeChar - When a character (identified by getCharAndSize) is consumed /// and added to a given token, check to see if there are diagnostics that /// need to be emitted or flags that need to be set on the token. If so, do @@ -503,22 +526,6 @@ private: /// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize /// method. char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0); -public: - - /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever - /// emit a warning. - static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, - const LangOptions &LangOpts) { - // If this is not a trigraph and not a UCN or escaped newline, return - // quickly. - if (isObviouslySimpleCharacter(Ptr[0])) { - Size = 1; - return *Ptr; - } - - Size = 0; - return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts); - } /// getEscapedNewLineSize - Return the size of the specified escaped newline, /// or 0 if it is not an escaped newline. P[-1] is known to be a "\" on entry @@ -530,22 +537,6 @@ public: /// otherwise return P. static const char *SkipEscapedNewLines(const char *P); - /// \brief Checks that the given token is the first token that occurs after - /// the given location (this excludes comments and whitespace). Returns the - /// location immediately after the specified token. If the token is not found - /// or the location is inside a macro, the returned source location will be - /// invalid. - static SourceLocation findLocationAfterToken(SourceLocation loc, - tok::TokenKind TKind, - const SourceManager &SM, - const LangOptions &LangOpts, - bool SkipTrailingWhitespaceAndNewLine); - - /// \brief Returns true if the given character could appear in an identifier. - static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts); - -private: - /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a /// diagnostic. static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size, @@ -571,15 +562,17 @@ private: bool LexEndOfFile (Token &Result, const char *CurPtr); bool SkipWhitespace (Token &Result, const char *CurPtr); - bool SkipBCPLComment (Token &Result, const char *CurPtr); + bool SkipLineComment (Token &Result, const char *CurPtr); bool SkipBlockComment (Token &Result, const char *CurPtr); - bool SaveBCPLComment (Token &Result, const char *CurPtr); + bool SaveLineComment (Token &Result, const char *CurPtr); bool IsStartOfConflictMarker(const char *CurPtr); bool HandleEndOfConflictMarker(const char *CurPtr); bool isCodeCompletionPoint(const char *CurPtr) const; void cutOffLexing() { BufferPtr = BufferEnd; } + + bool isHexaLiteral(const char *Start, const LangOptions &LangOpts); }; diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index bbce62d1d48a..3b68d1b570f4 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.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> @@ -48,8 +49,9 @@ class NumericLiteralParser { bool saw_exponent, saw_period, saw_ud_suffix; public: - NumericLiteralParser(const char *begin, const char *end, - SourceLocation Loc, Preprocessor &PP); + NumericLiteralParser(StringRef TokSpelling, + SourceLocation TokLoc, + Preprocessor &PP); bool hadError; bool isUnsigned; bool isLong; // This is *not* set for long long. @@ -230,8 +232,8 @@ public: private: void init(const Token *StringToks, unsigned NumStringToks); - bool CopyStringFragment(StringRef Fragment); - bool DiagnoseBadString(const Token& Tok); + bool CopyStringFragment(const Token &Tok, const char *TokBegin, + StringRef Fragment); void DiagnoseLexingError(SourceLocation Loc); }; diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index cbd201f849de..aba77d580d9b 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -32,6 +32,12 @@ class MacroInfo { SourceLocation Location; /// EndLocation - 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 @@ -99,7 +105,16 @@ private: /// \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 the definition of this macro is ambiguous, due to + /// multiple definitions coming in from multiple modules. + bool IsAmbiguous : 1; + ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); } @@ -128,10 +143,34 @@ public: /// setDefinitionEndLoc - 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. /// 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) @@ -294,6 +333,23 @@ public: /// \brief Determine the location where this macro was explicitly made /// public or private within its module. SourceLocation getVisibilityLocation() { return VisibilityLocation; } + + /// \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 Determine whether this macro definition is hidden. + bool isHidden() const { return IsHidden; } + + /// \brief Set whether this macro definition is hidden. + void setHidden(bool Val) { IsHidden = Val; } + + /// \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; diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index fe5abdfba7ad..082408d83ce3 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -52,10 +52,37 @@ class ModuleMap { /// \brief The top-level modules that are known. llvm::StringMap<Module *> Modules; - + + /// \brief A header that is known to reside within a given module, + /// whether it was included or excluded. + class KnownHeader { + llvm::PointerIntPair<Module *, 1, bool> Storage; + + public: + KnownHeader() : Storage(0, false) { } + KnownHeader(Module *M, bool Excluded) : Storage(M, Excluded) { } + + /// \brief Retrieve the module the header is stored in. + Module *getModule() const { return Storage.getPointer(); } + + /// \brief Whether this header is explicitly excluded from the module. + bool isExcluded() const { return Storage.getInt(); } + + /// \brief Whether this header is available in the module. + bool isAvailable() const { + return !isExcluded() && getModule()->isAvailable(); + } + + // \brief Whether this known header is valid (i.e., it has an + // associated module). + operator bool() const { return Storage.getPointer() != 0; } + }; + + typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap; + /// \brief Mapping from each header to the module that owns the contents of the /// that header. - llvm::DenseMap<const FileEntry *, Module *> Headers; + HeadersMap Headers; /// \brief Mapping from directories with umbrella headers to the module /// that is generated from the umbrella header. @@ -64,7 +91,26 @@ class ModuleMap { /// in the module map over to the module that includes them via its umbrella /// header. llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs; - + + /// \brief A directory for which framework modules can be inferred. + struct InferredDirectory { + InferredDirectory() : InferModules(), InferSystemModules() { } + + /// \brief Whether to infer modules from this directory. + unsigned InferModules : 1; + + /// \brief Whether the modules we infer are [system] modules. + unsigned InferSystemModules : 1; + + /// \brief The names of modules that cannot be inferred within this + /// directory. + llvm::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; + friend class ModuleMapParser; /// \brief Resolve the given export declaration into an actual export @@ -170,7 +216,23 @@ public: std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit); - + + /// \brief Determine whether we can infer a framework module a framework + /// with the given name in the given + /// + /// \param ParentDir The directory that is the parent of the framework + /// directory. + /// + /// \param Name The name of the module. + /// + /// \param IsSystem Will be set to 'true' if the inferred module must be a + /// system module. + /// + /// \returns true if we are allowed to infer a framework module, and false + /// otherwise. + bool canInferFrameworkModule(const DirectoryEntry *ParentDir, + StringRef Name, bool &IsSystem); + /// \brief Infer the contents of a framework module map from the given /// framework directory. Module *inferFrameworkModule(StringRef ModuleName, @@ -215,7 +277,9 @@ public: void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir); /// \brief Adds this header to the given module. - void addHeader(Module *Mod, const FileEntry *Header); + /// \param Excluded Whether this header is explicitly excluded from the + /// module; otherwise, it's included in the module. + void addHeader(Module *Mod, const FileEntry *Header, bool Excluded); /// \brief Parse the given module map file, and record any modules we /// encounter. diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 962b4df6c492..8ba02cc4ea23 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_LEX_PPCALLBACKS_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" @@ -93,10 +94,10 @@ public: /// \param IsAngled Whether the file name was enclosed in angle brackets; /// otherwise, it was enclosed in quotes. /// - /// \param File The actual file that may be included by this inclusion - /// directive. + /// \param FilenameRange The character range of the quotes or angle brackets + /// for the written file name. /// - /// \param EndLoc The location of the last token within the inclusion + /// \param File The actual file that may be included by this inclusion /// directive. /// /// \param SearchPath Contains the search path which was used to find the file @@ -110,14 +111,34 @@ public: /// /// \param RelativePath The path relative to SearchPath, at which the include /// file was found. This is equal to FileName except for framework includes. + /// + /// \param Imported The module, whenever an inclusion directive was + /// automatically turned into a module import or null otherwise. + /// virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, - SourceLocation EndLoc, StringRef SearchPath, - StringRef RelativePath) { + StringRef RelativePath, + const Module *Imported) { + } + + /// \brief Callback invoked whenever there was an explicit module-import + /// syntax. + /// + /// \param ImportLoc The location of import directive token. + /// + /// \param Path The identifiers (and their locations) of the module + /// "path", e.g., "std.vector" would be split into "std" and "vector". + /// + /// \param Imported The imported module; can be null if importing failed. + /// + virtual void moduleImport(SourceLocation ImportLoc, + ModuleIdPath Path, + const Module *Imported) { } /// \brief Callback invoked when the end of the main file is reached. @@ -266,14 +287,24 @@ public: const Token &IncludeTok, StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, - SourceLocation EndLoc, StringRef SearchPath, - StringRef RelativePath) { - First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc, SearchPath, RelativePath); - Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc, SearchPath, RelativePath); + StringRef RelativePath, + const Module *Imported) { + First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, + FilenameRange, File, SearchPath, RelativePath, + Imported); + Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, + FilenameRange, File, SearchPath, RelativePath, + Imported); + } + + virtual void moduleImport(SourceLocation ImportLoc, + ModuleIdPath Path, + const Module *Imported) { + First->moduleImport(ImportLoc, Path, Imported); + Second->moduleImport(ImportLoc, Path, Imported); } virtual void EndOfMainFile() { diff --git a/include/clang/Lex/PPMutationListener.h b/include/clang/Lex/PPMutationListener.h new file mode 100644 index 000000000000..5319c66fa27d --- /dev/null +++ b/include/clang/Lex/PPMutationListener.h @@ -0,0 +1,43 @@ +//===--- 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/PTHLexer.h b/include/clang/Lex/PTHLexer.h index f6a97a0a90a4..a9276e86b726 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -44,8 +44,8 @@ class PTHLexer : public PreprocessorLexer { /// to process when doing quick skipping of preprocessor blocks. const unsigned char* CurPPCondPtr; - PTHLexer(const PTHLexer&); // DO NOT IMPLEMENT - void operator=(const PTHLexer&); // DO NOT IMPLEMENT + PTHLexer(const PTHLexer &) LLVM_DELETED_FUNCTION; + void operator=(const PTHLexer &) LLVM_DELETED_FUNCTION; /// ReadToken - Used by PTHLexer to read tokens TokBuf. void ReadToken(Token& T); diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index 44f9ab39f321..e64dbd8bbcb0 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -81,9 +81,8 @@ class PTHManager : public IdentifierInfoLookup { void* stringIdLookup, unsigned numIds, const unsigned char* spellingBase, const char *originalSourceFile); - // Do not implement. - PTHManager(); - void operator=(const PTHManager&); + PTHManager(const PTHManager &) LLVM_DELETED_FUNCTION; + void operator=(const PTHManager &) LLVM_DELETED_FUNCTION; /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached /// spelling for a token. diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index fb3e081961bf..57e51b754e42 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -94,9 +94,6 @@ namespace clang { /// entity. bool isInvalid() const { return Kind == InvalidKind; } - // Implement isa/cast/dyncast/etc. - static bool classof(const PreprocessedEntity *) { return true; } - // Only allow allocation of preprocessed entities using the allocator // in PreprocessingRecord or by doing a placement new. void* operator new(size_t bytes, PreprocessingRecord& PR, @@ -133,7 +130,6 @@ namespace clang { return PD->getKind() >= FirstPreprocessingDirective && PD->getKind() <= LastPreprocessingDirective; } - static bool classof(const PreprocessingDirective *) { return true; } }; /// \brief Record the location of a macro definition. @@ -155,7 +151,6 @@ namespace clang { static bool classof(const PreprocessedEntity *PE) { return PE->getKind() == MacroDefinitionKind; } - static bool classof(const MacroDefinition *) { return true; } }; /// \brief Records the location of a macro expansion. @@ -193,7 +188,6 @@ namespace clang { static bool classof(const PreprocessedEntity *PE) { return PE->getKind() == MacroExpansionKind; } - static bool classof(const MacroExpansion *) { return true; } }; /// \brief Record the location of an inclusion directive, such as an @@ -227,13 +221,18 @@ namespace clang { /// This is a value of type InclusionKind. unsigned Kind : 2; + /// \brief Whether the inclusion directive was automatically turned into + /// a module import. + unsigned ImportedModule : 1; + /// \brief The file that was included. const FileEntry *File; public: InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind, StringRef FileName, - bool InQuotes, const FileEntry *File, SourceRange Range); + bool InQuotes, bool ImportedModule, + const FileEntry *File, SourceRange Range); /// \brief Determine what kind of inclusion directive this is. InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); } @@ -244,6 +243,10 @@ namespace clang { /// \brief Determine whether the included file name was written in quotes; /// otherwise, it was written in angle brackets. bool wasInQuotes() const { return InQuotes; } + + /// \brief Determine whether the inclusion directive was automatically + /// turned into a module import. + bool importedModule() const { return ImportedModule; } /// \brief Retrieve the file entry for the actual file that was included /// by this directive. @@ -253,7 +256,6 @@ namespace clang { static bool classof(const PreprocessedEntity *PE) { return PE->getKind() == InclusionDirectiveKind; } - static bool classof(const InclusionDirective *) { return true; } }; /// \brief An abstract class that should be subclassed by any external source @@ -269,12 +271,12 @@ namespace clang { virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0; /// \brief Returns a pair of [Begin, End) indices of preallocated - /// preprocessed entities that \arg Range encompasses. + /// preprocessed entities that \p Range encompasses. virtual std::pair<unsigned, unsigned> findPreprocessedEntitiesInRange(SourceRange Range) = 0; /// \brief Optionally returns true or false if the preallocated preprocessed - /// entity with index \arg Index came from file \arg FID. + /// entity with index \p Index came from file \p FID. virtual llvm::Optional<bool> isPreprocessedEntityInFileID(unsigned Index, FileID FID) { return llvm::Optional<bool>(); @@ -343,14 +345,21 @@ namespace clang { /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to /// indicate preprocessed entities introduced by the current preprocessor. - /// If M is the number of loaded preprocessed entities, value -M - /// corresponds to element 0 in the loaded entities vector, position -M+1 - /// corresponds to element 1 in the loaded entities vector, etc. - typedef int PPEntityID; - - PPEntityID getPPEntityID(unsigned Index, bool isLoaded) const { - return isLoaded ? PPEntityID(Index) - LoadedPreprocessedEntities.size() - : Index; + /// Value -1 corresponds to element 0 in the loaded entities vector, + /// value -2 corresponds to element 1 in the loaded entities vector, etc. + /// Value 0 is an invalid value, the index to local entities is 1-based, + /// 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; + public: + PPEntityID() : ID(0) {} + }; + + static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) { + return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1); } /// \brief Mapping from MacroInfo structures to their definitions. @@ -372,7 +381,7 @@ namespace clang { } /// \brief Returns a pair of [Begin, End) indices of local preprocessed - /// entities that \arg Range encompasses. + /// entities that \p Range encompasses. std::pair<unsigned, unsigned> findLocalPreprocessedEntitiesInRange(SourceRange Range) const; unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const; @@ -419,7 +428,7 @@ namespace clang { /// corresponds to element 0 in the loaded entities vector, position -M+1 /// corresponds to element 1 in the loaded entities vector, etc. This /// gives us a reasonably efficient, source-order walk. - PPEntityID Position; + int Position; public: typedef PreprocessedEntity *value_type; @@ -430,11 +439,15 @@ namespace clang { iterator() : Self(0), Position(0) { } - iterator(PreprocessingRecord *Self, PPEntityID Position) + iterator(PreprocessingRecord *Self, int Position) : Self(Self), Position(Position) { } value_type operator*() const { - return Self->getPreprocessedEntity(Position); + bool isLoaded = Position < 0; + unsigned Index = isLoaded ? + Self->LoadedPreprocessedEntities.size() + Position : Position; + PPEntityID ID = Self->getPPEntityID(Index, isLoaded); + return Self->getPreprocessedEntity(ID); } value_type operator[](difference_type D) { @@ -539,15 +552,26 @@ namespace clang { return iterator(this, PreprocessedEntities.size()); } + /// \brief begin/end iterator pair for the given range of loaded + /// preprocessed entities. + std::pair<iterator, iterator> + getIteratorsForLoadedRange(unsigned start, unsigned count) { + unsigned end = start + count; + assert(end <= LoadedPreprocessedEntities.size()); + return std::make_pair( + iterator(this, int(start)-LoadedPreprocessedEntities.size()), + iterator(this, int(end)-LoadedPreprocessedEntities.size())); + } + /// \brief Returns a pair of [Begin, End) iterators of preprocessed entities - /// that source range \arg R encompasses. + /// that source range \p R encompasses. /// /// \param R the range to look for preprocessed entities. /// std::pair<iterator, iterator> getPreprocessedEntitiesInRange(SourceRange R); - /// \brief Returns true if the preprocessed entity that \arg PPEI iterator - /// points to is coming from the file \arg FID. + /// \brief Returns true if the preprocessed entity that \p PPEI iterator + /// points to is coming from the file \p FID. /// /// Can be used to avoid implicit deserializations of preallocated /// preprocessed entities if we only care about entities of a specific file @@ -597,10 +621,11 @@ namespace clang { const Token &IncludeTok, StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, - SourceLocation EndLoc, StringRef SearchPath, - StringRef RelativePath); + StringRef RelativePath, + const Module *Imported); virtual void If(SourceLocation Loc, SourceRange ConditionRange); virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, SourceLocation IfLoc); @@ -613,11 +638,10 @@ namespace clang { /// query. struct { SourceRange Range; - std::pair<PPEntityID, PPEntityID> Result; + std::pair<int, int> Result; } CachedRangeQuery; - std::pair<PPEntityID, PPEntityID> - getPreprocessedEntitiesInRangeSlow(SourceRange R); + std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R); friend class ASTReader; friend class ASTWriter; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 02e3f1e7e439..e9095fbf44a9 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -18,6 +18,7 @@ #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" @@ -54,6 +55,28 @@ class CodeCompletionHandler; class DirectoryLookup; class PreprocessingRecord; class ModuleLoader; +class PreprocessorOptions; + +/// \brief Stores token information for comparing actual tokens with +/// predefined values. Only handles simple tokens and identifiers. +class TokenValue { + tok::TokenKind Kind; + IdentifierInfo *II; + +public: + TokenValue(tok::TokenKind Kind) : Kind(Kind), II(0) { + assert(Kind != tok::raw_identifier && "Raw identifiers are not supported."); + assert(Kind != tok::identifier && + "Identifiers should be created by TokenValue(IdentifierInfo *)"); + 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()); + } +}; /// Preprocessor - This object engages in a tight little dance with the lexer to /// efficiently preprocess tokens. Lexers know only about tokens within a @@ -61,6 +84,7 @@ class ModuleLoader; /// like the \#include stack, token expansion, etc. /// class Preprocessor : public RefCountedBase<Preprocessor> { + llvm::IntrusiveRefCntPtr<PreprocessorOptions> PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; const TargetInfo *Target; @@ -98,6 +122,8 @@ class Preprocessor : public RefCountedBase<Preprocessor> { IdentifierInfo *Ident__has_include; // __has_include IdentifierInfo *Ident__has_include_next; // __has_include_next IdentifierInfo *Ident__has_warning; // __has_warning + IdentifierInfo *Ident__building_module; // __building_module + IdentifierInfo *Ident__MODULE__; // __MODULE__ SourceLocation DATELoc, TIMELoc; unsigned CounterValue; // Next __COUNTER__ value. @@ -265,6 +291,11 @@ 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; @@ -274,10 +305,12 @@ class Preprocessor : public RefCountedBase<Preprocessor> { }; SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; - /// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping - /// to the actual definition of the macro. + /// 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; - + friend class ASTReader; + /// \brief Macros that we want to warn because they are not used at the end /// of the translation unit; we store just their SourceLocations instead /// something like MacroInfo*. The benefit of this is that when we are @@ -362,10 +395,9 @@ private: // Cached tokens state. /// allocation. MacroInfoChain *MICache; - MacroInfo *getInfoForMacro(IdentifierInfo *II) const; - public: - Preprocessor(DiagnosticsEngine &diags, LangOptions &opts, + Preprocessor(llvm::IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, + DiagnosticsEngine &diags, LangOptions &opts, const TargetInfo *target, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, @@ -382,6 +414,10 @@ public: /// \param Target Information about the target. void Initialize(const TargetInfo &Target); + /// \brief Retrieve the preprocessor options used to initialize this + /// preprocessor. + PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; } + DiagnosticsEngine &getDiagnostics() const { return *Diags; } void setDiagnostics(DiagnosticsEngine &D) { Diags = &D; } @@ -457,37 +493,70 @@ 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 { if (!II->hasMacroDefinition()) return 0; - return getInfoForMacro(II); + MacroInfo *MI = getMacroInfoHistory(II); + assert(MI->getUndefLoc().isInvalid() && "Macro is undefined!"); + return MI; } - /// \brief Specify a macro for this identifier. - void setMacroInfo(IdentifierInfo *II, MacroInfo *MI, - bool LoadedFromAST = false); + /// \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; - /// macro_iterator/macro_begin/macro_end - This allows you to walk the current - /// state of the macro table. This visits every currently-defined macro. + /// \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); + + /// 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; macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; + /// \brief Return the name of the macro defined before \p Loc that has + /// spelling \p Tokens. If there are multiple macros with same spelling, + /// return the last one defined. + StringRef getLastMacroWithSpelling(SourceLocation Loc, + ArrayRef<TokenValue> Tokens) const; + const std::string &getPredefines() const { return Predefines; } /// setPredefines - Set the predefines for this Preprocessor. These /// predefines are automatically injected when parsing the main file. void setPredefines(const char *P) { Predefines = P; } void setPredefines(const std::string &P) { Predefines = P; } - /// getIdentifierInfo - Return information about the specified preprocessor - /// identifier token. The version of this method that takes two character - /// pointers is preferred unless the identifier is already available as a - /// string (this avoids allocation and copying of memory to construct an - /// std::string). + /// Return information about the specified preprocessor + /// identifier token. IdentifierInfo *getIdentifierInfo(StringRef Name) const { return &Identifiers.get(Name); } @@ -501,8 +570,8 @@ public: } /// RemovePragmaHandler - Remove the specific pragma handler from - /// the preprocessor. If \arg Namespace is non-null, then it should - /// be the namespace that \arg Handler was added to. It is an error + /// the preprocessor. If \p Namespace is non-null, then it should + /// be the namespace that \p Handler was added to. It is an error /// to remove a handler that has not been registered. void RemovePragmaHandler(StringRef Namespace, PragmaHandler *Handler); void RemovePragmaHandler(PragmaHandler *Handler) { @@ -564,7 +633,8 @@ public: /// /// ILEnd specifies the location of the ')' for a function-like macro or the /// identifier for an object-like macro. - void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroArgs *Args); + void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroInfo *Macro, + MacroArgs *Args); /// EnterTokenStream - Add a "macro" context to the top of the include stack, /// which will cause the lexer to start returning the specified tokens. @@ -724,6 +794,14 @@ public: CachedTokens[CachedLexPos-1] = Tok; } + /// TypoCorrectToken - Update the current token to represent the provided + /// identifier, in order to cache an action performed by typo correction. + void TypoCorrectToken(const Token &Tok) { + assert(Tok.getIdentifierInfo() && "Expected identifier token"); + if (CachedLexPos != 0 && isBacktrackEnabled()) + CachedTokens[CachedLexPos-1] = Tok; + } + /// \brief Recompute the current lexer kind based on the CurLexer/CurPTHLexer/ /// CurTokenLexer pointers. void recomputeCurLexerKind(); @@ -892,7 +970,7 @@ public: /// CreateString - Plop the specified string into a scratch buffer and set the /// specified token's location and length to it. If specified, the source /// location provides a location of the expansion point of the token. - void CreateString(const char *Buf, unsigned Len, Token &Tok, + void CreateString(StringRef Str, Token &Tok, SourceLocation ExpansionLocStart = SourceLocation(), SourceLocation ExpansionLocEnd = SourceLocation()); @@ -929,7 +1007,7 @@ public: /// \brief Returns true if the given MacroID location points at the last /// token of the macro expansion. /// - /// \param MacroBegin If non-null and function returns true, it is set to + /// \param MacroEnd If non-null and function returns true, it is set to /// end location of the macro. bool isAtEndOfMacroExpansion(SourceLocation loc, SourceLocation *MacroEnd = 0) const { @@ -1103,10 +1181,10 @@ public: /// from a macro as multiple tokens, which need to be glued together. This /// occurs for code like: /// \code - /// \#define FOO <a/b.h> + /// \#define FOO <x/y.h> /// \#include FOO /// \endcode - /// because in this case, "<a/b.h>" is returned as 7 tokens, not one. + /// because in this case, "<x/y.h>" is returned as 7 tokens, not one. /// /// This code concatenates and consumes tokens up to the '>' token. It /// returns false if the > was found, otherwise it returns true if it finds @@ -1289,6 +1367,8 @@ 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/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index 8a0b3cf51acc..20fb8a0c4804 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -69,8 +69,8 @@ protected: /// we are currently in. SmallVector<PPConditionalInfo, 4> ConditionalStack; - PreprocessorLexer(const PreprocessorLexer&); // DO NOT IMPLEMENT - void operator=(const PreprocessorLexer&); // DO NOT IMPLEMENT + PreprocessorLexer(const PreprocessorLexer &) LLVM_DELETED_FUNCTION; + void operator=(const PreprocessorLexer &) LLVM_DELETED_FUNCTION; friend class Preprocessor; PreprocessorLexer(Preprocessor *pp, FileID fid); diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h new file mode 100644 index 000000000000..e5fe37379355 --- /dev/null +++ b/include/clang/Lex/PreprocessorOptions.h @@ -0,0 +1,221 @@ +//===--- PreprocessorOptions.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ +#define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <string> +#include <utility> +#include <vector> +#include <set> + +namespace llvm { + class MemoryBuffer; +} + +namespace clang { + +class Preprocessor; +class LangOptions; + +/// \brief Enumerate the kinds of standard library that +enum ObjCXXARCStandardLibraryKind { + ARCXX_nolib, + /// \brief libc++ + ARCXX_libcxx, + /// \brief libstdc++ + ARCXX_libstdcxx +}; + +/// PreprocessorOptions - This class is used for passing the various options +/// used in preprocessor initialization to InitializePreprocessor(). +class PreprocessorOptions : public llvm::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. + + 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; + + /// \brief Headers that will be converted to chained PCHs in memory. + std::vector<std::string> ChainedIncludes; + + /// \brief When true, disables most of the normal validation performed on + /// precompiled headers. + bool DisablePCHValidation; + + /// \brief When true, a PCH with compiler errors will not be rejected. + bool AllowPCHWithCompilerErrors; + + /// \brief Dump declarations that are deserialized from PCH, for testing. + bool DumpDeserializedPCHDecls; + + /// \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. + std::set<std::string> DeserializedPCHDeclsToErrorOn; + + /// \brief If non-zero, the implicit PCH include is actually a precompiled + /// preamble that covers this number of bytes in the main source file. + /// + /// The boolean indicates whether the preamble ends at the start of a new + /// line. + std::pair<unsigned, bool> PrecompiledPreambleBytes; + + /// The implicit PTH input included at the start of the translation unit, or + /// empty. + std::string ImplicitPTHInclude; + + /// If given, a PTH cache file to use for speeding up header parsing. + std::string TokenCache; + + /// \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; + + /// \brief The set of file remappings, which take existing files on + /// the system (the first part of each pair) and gives them the + /// contents of other files on the system (the second part of each + /// pair). + std::vector<std::pair<std::string, std::string> > RemappedFiles; + + /// \brief The set of file-to-buffer remappings, which take existing files + /// on the system (the first part of each pair) and gives them the contents + /// of the specified memory buffer (the second part of each pair). + std::vector<std::pair<std::string, const llvm::MemoryBuffer *> > + RemappedFileBuffers; + + /// \brief Whether the compiler instance should retain (i.e., not free) + /// the buffers associated with remapped files. + /// + /// 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; + + /// \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; + + /// \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; + + typedef std::vector<std::pair<std::string, std::string> >::iterator + remapped_file_iterator; + typedef std::vector<std::pair<std::string, std::string> >::const_iterator + const_remapped_file_iterator; + remapped_file_iterator remapped_file_begin() { + return RemappedFiles.begin(); + } + const_remapped_file_iterator remapped_file_begin() const { + return RemappedFiles.begin(); + } + remapped_file_iterator remapped_file_end() { + return RemappedFiles.end(); + } + const_remapped_file_iterator remapped_file_end() const { + return RemappedFiles.end(); + } + + typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >:: + iterator remapped_file_buffer_iterator; + typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >:: + const_iterator const_remapped_file_buffer_iterator; + remapped_file_buffer_iterator remapped_file_buffer_begin() { + return RemappedFileBuffers.begin(); + } + const_remapped_file_buffer_iterator remapped_file_buffer_begin() const { + return RemappedFileBuffers.begin(); + } + remapped_file_buffer_iterator remapped_file_buffer_end() { + return RemappedFileBuffers.end(); + } + const_remapped_file_buffer_iterator remapped_file_buffer_end() const { + return RemappedFileBuffers.end(); + } + +public: + PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), + DetailedRecordConditionalDirectives(false), + DisablePCHValidation(false), + AllowPCHWithCompilerErrors(false), + DumpDeserializedPCHDecls(false), + PrecompiledPreambleBytes(0, true), + RemappedFilesKeepOriginalName(true), + RetainRemappedFileBuffers(false), + ObjCXXARCStandardLibrary(ARCXX_nolib) { } + + void addMacroDef(StringRef Name) { + Macros.push_back(std::make_pair(Name, false)); + } + void addMacroUndef(StringRef Name) { + Macros.push_back(std::make_pair(Name, true)); + } + void addRemappedFile(StringRef From, StringRef To) { + RemappedFiles.push_back(std::make_pair(From, To)); + } + + remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) { + return RemappedFiles.erase(Remapped); + } + + void addRemappedFile(StringRef From, const llvm::MemoryBuffer * To) { + RemappedFileBuffers.push_back(std::make_pair(From, To)); + } + + remapped_file_buffer_iterator + eraseRemappedFile(remapped_file_buffer_iterator Remapped) { + return RemappedFileBuffers.erase(Remapped); + } + + void clearRemappedFiles() { + RemappedFiles.clear(); + RemappedFileBuffers.clear(); + } + + /// \brief Reset any options that are not considered when building a + /// module. + void resetNonModularOptions() { + Includes.clear(); + MacroIncludes.clear(); + ChainedIncludes.clear(); + DumpDeserializedPCHDecls = false; + ImplicitPCHInclude.clear(); + ImplicitPTHInclude.clear(); + TokenCache.clear(); + RetainRemappedFileBuffers = true; + PrecompiledPreambleBytes.first = 0; + PrecompiledPreambleBytes.second = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 9c5a023f30d9..50b86c84e571 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -90,26 +90,18 @@ public: /// \brief Return true if this is a raw identifier (when lexing /// in raw mode) or a non-keyword identifier (when lexing in non-raw mode). bool isAnyIdentifier() const { - return is(tok::identifier) || is(tok::raw_identifier); + return tok::isAnyIdentifier(getKind()); } - /// isLiteral - Return true if this is a "literal", like a numeric + /// \brief Return true if this is a "literal", like a numeric /// constant, string, etc. bool isLiteral() const { - return is(tok::numeric_constant) || is(tok::char_constant) || - is(tok::wide_char_constant) || is(tok::utf16_char_constant) || - is(tok::utf32_char_constant) || is(tok::string_literal) || - is(tok::wide_string_literal) || is(tok::utf8_string_literal) || - is(tok::utf16_string_literal) || is(tok::utf32_string_literal) || - is(tok::angle_string_literal); + return tok::isLiteral(getKind()); } + /// \brief Return true if this is any of tok::annot_* kind tokens. bool isAnnotation() const { -#define ANNOTATION(NAME) \ - if (is(tok::annot_##NAME)) \ - return true; -#include "clang/Basic/TokenKinds.def" - return false; + return tok::isAnnotation(getKind()); } /// \brief Return a source location identifier for the specified diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index 1330ad5f3143..090402a811e2 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -22,7 +22,7 @@ namespace clang { class Token; class MacroArgs; -/// TokenLexer - This implements a lexer that returns token from a macro body +/// 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. /// @@ -91,24 +91,25 @@ class TokenLexer { /// should not be subject to further macro expansion. bool DisableMacroExpansion : 1; - TokenLexer(const TokenLexer&); // DO NOT IMPLEMENT - void operator=(const TokenLexer&); // DO NOT IMPLEMENT + TokenLexer(const TokenLexer &) LLVM_DELETED_FUNCTION; + void operator=(const TokenLexer &) LLVM_DELETED_FUNCTION; public: /// Create a TokenLexer for the specified macro with the specified actual /// arguments. 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. - TokenLexer(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs, - Preprocessor &pp) + TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, + MacroArgs *ActualArgs, Preprocessor &pp) : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) { - Init(Tok, ILEnd, ActualArgs); + 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, MacroArgs *ActualArgs); + 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 @@ -168,7 +169,7 @@ private: /// first token on the next line. void HandleMicrosoftCommentPaste(Token &Tok); - /// \brief If \arg loc is a FileID and points inside the current macro + /// \brief If \p loc is a FileID and points inside the current macro /// definition, returns the appropriate source location pointing at the /// macro expansion source location entry. SourceLocation getExpansionLocForMacroDefLoc(SourceLocation loc) const; |
