aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Lex
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
commit13cc256e404620c1de0cbcc4e43ce1e2dbbc4898 (patch)
tree2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /include/clang/Lex
parent657bc3d9848e3be92029b2416031340988cd0111 (diff)
Diffstat (limited to 'include/clang/Lex')
-rw-r--r--include/clang/Lex/ExternalPreprocessorSource.h3
-rw-r--r--include/clang/Lex/HeaderMap.h5
-rw-r--r--include/clang/Lex/HeaderSearch.h25
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h147
-rw-r--r--include/clang/Lex/Lexer.h91
-rw-r--r--include/clang/Lex/LiteralSupport.h10
-rw-r--r--include/clang/Lex/MacroInfo.h60
-rw-r--r--include/clang/Lex/ModuleMap.h74
-rw-r--r--include/clang/Lex/PPCallbacks.h53
-rw-r--r--include/clang/Lex/PPMutationListener.h43
-rw-r--r--include/clang/Lex/PTHLexer.h4
-rw-r--r--include/clang/Lex/PTHManager.h5
-rw-r--r--include/clang/Lex/PreprocessingRecord.h84
-rw-r--r--include/clang/Lex/Preprocessor.h128
-rw-r--r--include/clang/Lex/PreprocessorLexer.h4
-rw-r--r--include/clang/Lex/PreprocessorOptions.h221
-rw-r--r--include/clang/Lex/Token.h18
-rw-r--r--include/clang/Lex/TokenLexer.h17
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;