diff options
Diffstat (limited to 'include/clang/Lex')
-rw-r--r-- | include/clang/Lex/CMakeLists.txt | 6 | ||||
-rw-r--r-- | include/clang/Lex/ExternalPreprocessorSource.h | 3 | ||||
-rw-r--r-- | include/clang/Lex/HeaderMap.h | 2 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 61 | ||||
-rw-r--r-- | include/clang/Lex/LexDiagnostic.h | 2 | ||||
-rw-r--r-- | include/clang/Lex/Lexer.h | 53 | ||||
-rw-r--r-- | include/clang/Lex/LiteralSupport.h | 31 | ||||
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 13 | ||||
-rw-r--r-- | include/clang/Lex/Makefile | 13 | ||||
-rw-r--r-- | include/clang/Lex/PPCallbacks.h | 139 | ||||
-rw-r--r-- | include/clang/Lex/PTHManager.h | 6 | ||||
-rw-r--r-- | include/clang/Lex/Pragma.h | 31 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessingRecord.h | 93 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 106 | ||||
-rw-r--r-- | include/clang/Lex/PreprocessorLexer.h | 12 | ||||
-rw-r--r-- | include/clang/Lex/Token.h | 42 |
16 files changed, 529 insertions, 84 deletions
diff --git a/include/clang/Lex/CMakeLists.txt b/include/clang/Lex/CMakeLists.txt new file mode 100644 index 0000000..b823e83 --- /dev/null +++ b/include/clang/Lex/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td) +tablegen(AttrSpellings.inc + -gen-clang-attr-spelling-list + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) +add_custom_target(ClangAttrSpellings + DEPENDS AttrSpellings.inc) diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index 791d3fe..dbf7389 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -27,6 +27,9 @@ 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; }; } diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h index 9837e29..8a5c83e 100644 --- a/include/clang/Lex/HeaderMap.h +++ b/include/clang/Lex/HeaderMap.h @@ -43,7 +43,7 @@ public: /// HeaderMap::Create - This attempts to load the specified file as a header /// map. If it doesn't look like a HeaderMap, it gives up and returns null. - static const HeaderMap *Create(const FileEntry *FE); + static const HeaderMap *Create(const FileEntry *FE, FileManager &FM); /// LookupFile - Check to see if the specified relative filename is located in /// this HeaderMap. If so, open it and return its FileEntry. diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 80b38de..30bd4f5 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -29,7 +29,7 @@ class IdentifierInfo; /// file that is #included. struct HeaderFileInfo { /// isImport - True if this is a #import'd or #pragma once file. - bool isImport : 1; + unsigned isImport : 1; /// DirInfo - Keep track of whether this is a system header, and if so, /// whether it is C++ clean or not. This can be set by the include paths or @@ -37,10 +37,24 @@ struct HeaderFileInfo { /// SrcMgr::CharacteristicKind. unsigned DirInfo : 2; + /// \brief Whether this header file info was supplied by an external source. + unsigned External : 1; + + /// \brief Whether this structure is considered to already have been + /// "resolved", meaning that it was loaded from the external source. + unsigned Resolved : 1; + /// NumIncludes - This is the number of times the file has been included /// already. unsigned short NumIncludes; + /// \brief The ID number of the controlling macro. + /// + /// This ID number will be non-zero when there is a controlling + /// macro whose IdentifierInfo may not yet have been loaded from + /// external storage. + unsigned ControllingMacroID; + /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard /// that protects the entire contents of the file, this is the identifier /// for the macro that controls whether or not it has any effect. @@ -51,27 +65,40 @@ struct HeaderFileInfo { /// external storage. const IdentifierInfo *ControllingMacro; - /// \brief The ID number of the controlling macro. - /// - /// This ID number will be non-zero when there is a controlling - /// macro whose IdentifierInfo may not yet have been loaded from - /// external storage. - unsigned ControllingMacroID; - HeaderFileInfo() - : isImport(false), DirInfo(SrcMgr::C_User), - NumIncludes(0), ControllingMacro(0), ControllingMacroID(0) {} + : isImport(false), DirInfo(SrcMgr::C_User), External(false), + Resolved(false), NumIncludes(0), ControllingMacroID(0), + ControllingMacro(0) {} /// \brief Retrieve the controlling macro for this header file, if /// any. const IdentifierInfo *getControllingMacro(ExternalIdentifierLookup *External); + + /// \brief Determine whether this is a non-default header file info, e.g., + /// it corresponds to an actual header we've included or tried to include. + bool isNonDefault() const { + return isImport || NumIncludes || ControllingMacro || ControllingMacroID; + } }; +/// \brief An external source of header file information, which may supply +/// information about header files already included. +class ExternalHeaderFileInfoSource { +public: + virtual ~ExternalHeaderFileInfoSource(); + + /// \brief Retrieve the header file information for the given file entry. + /// + /// \returns Header file information for the given file entry, with the + /// \c External bit set. If the file entry is not known, return a + /// default-constructed \c HeaderFileInfo. + virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0; +}; + /// HeaderSearch - This class encapsulates the information needed to find the /// file referenced by a #include or #include_next, (sub-)framework lookup, etc. class HeaderSearch { FileManager &FileMgr; - /// #include search path information. Requests for #include "x" search the /// directory of the #including file first, then each directory in SearchDirs /// consequtively. Requests for <x> search the current dir first, then each @@ -108,6 +135,9 @@ class HeaderSearch { /// macros into IdentifierInfo pointers, as needed. ExternalIdentifierLookup *ExternalLookup; + /// \brief Entity used to look up stored header file information. + ExternalHeaderFileInfoSource *ExternalSource; + // Various statistics we track for performance analysis. unsigned NumIncluded; unsigned NumMultiIncludeFileOptzn; @@ -142,6 +172,15 @@ public: ExternalLookup = EIL; } + ExternalIdentifierLookup *getExternalLookup() const { + return ExternalLookup; + } + + /// \brief Set the external source of header information. + void SetExternalSource(ExternalHeaderFileInfoSource *ES) { + ExternalSource = ES; + } + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// a <> reference. If successful, this returns 'UsedDir', the diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h index 2d941e4..5fcb8eb 100644 --- a/include/clang/Lex/LexDiagnostic.h +++ b/include/clang/Lex/LexDiagnostic.h @@ -15,7 +15,7 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, #define LEXSTART #include "clang/Basic/DiagnosticLexKinds.inc" #undef DIAG diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 9e0fb7e..fc9a8de 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -211,6 +211,32 @@ public: /// and " characters. This does not add surrounding ""'s to the string. static void Stringify(llvm::SmallVectorImpl<char> &Str); + + /// getSpelling - This method is used to get the spelling of a token into a + /// preallocated buffer, instead of as an std::string. The caller is required + /// to allocate enough space for the token, which is guaranteed to be at least + /// Tok.getLength() bytes long. The length of the actual result is returned. + /// + /// Note that this method may do two possible things: it may either fill in + /// the buffer specified with characters, or it may *change the input pointer* + /// to point to a constant buffer with the data already in it (avoiding a + /// copy). The caller is not allowed to modify the returned buffer pointer + /// if an internal buffer is returned. + static unsigned getSpelling(const Token &Tok, const char *&Buffer, + const SourceManager &SourceMgr, + const LangOptions &Features, + bool *Invalid = 0); + + /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a + /// token is the characters used to represent the token in the source file + /// after trigraph expansion and escaped-newline folding. In particular, this + /// wants to get the true, uncanonicalized, spelling of things like digraphs + /// UCNs, etc. + static std::string getSpelling(const Token &Tok, + const SourceManager &SourceMgr, + const LangOptions &Features, + bool *Invalid = 0); + /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. /// includes a trigraph or an escaped newline) then this count includes bytes @@ -228,6 +254,33 @@ public: const SourceManager &SM, const LangOptions &LangOpts); + /// AdvanceToTokenCharacter - If the current SourceLocation specifies a + /// location at the start of a token, return a new location that specifies a + /// character within the token. This handles trigraphs and escaped newlines. + static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, + unsigned Character, + const SourceManager &SM, + const LangOptions &Features); + + /// \brief Computes the source location just past the end of the + /// token at this source location. + /// + /// This routine can be used to produce a source location that + /// points just past the end of the token referenced by \p Loc, and + /// is generally used when a diagnostic needs to point just after a + /// token where it expected something different that it received. If + /// the returned source location would not be meaningful (e.g., if + /// it points into a macro), this routine returns an invalid + /// source location. + /// + /// \param Offset an offset from the end of the token, where the source + /// location should refer to. The default offset (0) produces a source + /// location pointing just past the end of the token; an offset of 1 produces + /// a source location pointing to the last character in the token, etc. + static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, + const SourceManager &SM, + const LangOptions &Features); + /// \brief Compute the preamble of the given file. /// /// The preamble of a file contains the initial comments, include directives, diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index ba46fb1..bf2c06b 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -15,10 +15,11 @@ #ifndef CLANG_LITERALSUPPORT_H #define CLANG_LITERALSUPPORT_H -#include <string> #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" +#include <cctype> +#include <string> namespace clang { @@ -27,6 +28,8 @@ class Preprocessor; class Token; class SourceLocation; class TargetInfo; +class SourceManager; +class LangOptions; /// NumericLiteralParser - This performs strict semantic analysis of the content /// of a ppnumber, classifying it as either integer, floating, or erroneous, @@ -138,8 +141,11 @@ public: /// wide string analysis and Translation Phase #6 (concatenation of string /// literals) (C99 5.1.1.2p1). class StringLiteralParser { - Preprocessor &PP; - + const SourceManager &SM; + const LangOptions &Features; + const TargetInfo &Target; + Diagnostic *Diags; + unsigned MaxTokenLength; unsigned SizeBound; unsigned wchar_tByteWidth; @@ -148,6 +154,14 @@ class StringLiteralParser { public: StringLiteralParser(const Token *StringToks, unsigned NumStringToks, Preprocessor &PP, bool Complain = true); + StringLiteralParser(const Token *StringToks, unsigned NumStringToks, + const SourceManager &sm, const LangOptions &features, + const TargetInfo &target, Diagnostic *diags = 0) + : SM(sm), Features(features), Target(target), Diags(diags) { + init(StringToks, NumStringToks); + } + + bool hadError; bool AnyWide; bool Pascal; @@ -163,8 +177,13 @@ public: /// getOffsetOfStringByte - This function returns the offset of the /// specified byte of the string data represented by Token. This handles /// advancing over escape sequences in the string. - static unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo, - Preprocessor &PP, bool Complain = true); + /// + /// If the Diagnostics pointer is non-null, then this will do semantic + /// checking of the string literal and emit errors and warnings. + unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo) const; + +private: + void init(const Token *StringToks, unsigned NumStringToks); }; } // end namespace clang diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 90f95b7..717c300 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -82,6 +82,9 @@ private: /// AllowRedefinitionsWithoutWarning - True if this macro can be redefined /// without emitting a warning. bool IsAllowRedefinitionsWithoutWarning : 1; + + /// \brief Must warn if the macro is unused at the end of translation unit. + bool IsWarnIfUnused : 1; ~MacroInfo() { assert(ArgumentList == 0 && "Didn't call destroy before dtor!"); @@ -138,6 +141,11 @@ public: IsAllowRedefinitionsWithoutWarning = Val; } + /// \brief Set the value of the IsWarnIfUnused flag. + void setIsWarnIfUnused(bool val) { + IsWarnIfUnused = val; + } + /// setArgumentList - Set the specified list of identifiers as the argument /// list for this macro. void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs, @@ -201,6 +209,11 @@ public: return IsAllowRedefinitionsWithoutWarning; } + /// \brief Return true if we should emit a warning if the macro is unused. + bool isWarnIfUnused() const { + return IsWarnIfUnused; + } + /// getNumTokens - Return the number of tokens that this macro expands to. /// unsigned getNumTokens() const { diff --git a/include/clang/Lex/Makefile b/include/clang/Lex/Makefile new file mode 100644 index 0000000..9874bcf --- /dev/null +++ b/include/clang/Lex/Makefile @@ -0,0 +1,13 @@ +CLANG_LEVEL := ../../.. +TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic +BUILT_SOURCES = AttrSpellings.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(CLANG_LEVEL)/Makefile + +$(ObjDir)/AttrSpellings.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang attribute spellings with tblgen" + $(Verb) $(TableGen) -gen-clang-attr-spelling-list -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../../ $< diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 782f2d5..b2a80a6 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -54,12 +54,43 @@ public: SrcMgr::CharacteristicKind FileType) { } + /// \brief This callback is invoked whenever an inclusion directive of + /// any kind (\c #include, \c #import, etc.) has been processed, regardless + /// of whether the inclusion will actually result in an inclusion. + /// + /// \param HashLoc The location of the '#' that starts the inclusion + /// directive. + /// + /// \param IncludeTok The token that indicates the kind of inclusion + /// directive, e.g., 'include' or 'import'. + /// + /// \param FileName The name of the file being included, as written in the + /// source code. + /// + /// \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 EndLoc The location of the last token within the inclusion + /// directive. + virtual void InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, + llvm::StringRef FileName, + bool IsAngled, + const FileEntry *File, + SourceLocation EndLoc) { + } + /// EndOfMainFile - This callback is invoked when the end of the main file is /// reach, no subsequent callbacks will be made. virtual void EndOfMainFile() { } /// Ident - This callback is invoked when a #ident or #sccs directive is read. + /// \param Loc The location of the directive. + /// \param str The text of the directive. /// virtual void Ident(SourceLocation Loc, const std::string &str) { } @@ -73,6 +104,8 @@ public: /// PragmaMessage - This callback is invoked when a #pragma message directive /// is read. + /// \param Loc The location of the message directive. + /// \param str The text of the message directive. /// virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) { } @@ -80,17 +113,48 @@ public: /// MacroExpands - This is called by /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is /// found. - virtual void MacroExpands(const Token &Id, const MacroInfo* MI) { + virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) { } /// MacroDefined - This hook is called whenever a macro definition is seen. - virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) { + virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { } /// MacroUndefined - This hook is called whenever a macro #undef is seen. /// MI is released immediately following this callback. - virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II, - const MacroInfo *MI) { + virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { + } + + /// If -- This hook is called whenever an #if is seen. + /// \param Range The SourceRange of the expression being tested. + // FIXME: better to pass in a list (or tree!) of Tokens. + virtual void If(SourceRange Range) { + } + + /// Elif -- This hook is called whenever an #elif is seen. + /// \param Range The SourceRange of the expression being tested. + // FIXME: better to pass in a list (or tree!) of Tokens. + virtual void Elif(SourceRange Range) { + } + + /// Ifdef -- This hook is called whenever an #ifdef is seen. + /// \param Loc The location of the token being tested. + /// \param II Information on the token being tested. + virtual void Ifdef(const Token &MacroNameTok) { + } + + /// Ifndef -- This hook is called whenever an #ifndef is seen. + /// \param Loc The location of the token being tested. + /// \param II Information on the token being tested. + virtual void Ifndef(const Token &MacroNameTok) { + } + + /// Else -- This hook is called whenever an #else is seen. + virtual void Else() { + } + + /// Endif -- This hook is called whenever an #endif is seen. + virtual void Endif() { } }; @@ -119,6 +183,18 @@ public: Second->FileSkipped(ParentFile, FilenameTok, FileType); } + virtual void InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, + llvm::StringRef FileName, + bool IsAngled, + const FileEntry *File, + SourceLocation EndLoc) { + First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, + EndLoc); + Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, + EndLoc); + } + virtual void EndOfMainFile() { First->EndOfMainFile(); Second->EndOfMainFile(); @@ -140,20 +216,55 @@ public: Second->PragmaMessage(Loc, Str); } - virtual void MacroExpands(const Token &Id, const MacroInfo* MI) { - First->MacroExpands(Id, MI); - Second->MacroExpands(Id, MI); + virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI) { + First->MacroExpands(MacroNameTok, MI); + Second->MacroExpands(MacroNameTok, MI); + } + + virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { + First->MacroDefined(MacroNameTok, MI); + Second->MacroDefined(MacroNameTok, MI); + } + + virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { + First->MacroUndefined(MacroNameTok, MI); + Second->MacroUndefined(MacroNameTok, MI); + } + + /// If -- This hook is called whenever an #if is seen. + virtual void If(SourceRange Range) { + First->If(Range); + Second->If(Range); + } + + /// Elif -- This hook is called whenever an #if is seen. + virtual void Elif(SourceRange Range) { + First->Elif(Range); + Second->Elif(Range); + } + + /// Ifdef -- This hook is called whenever an #ifdef is seen. + virtual void Ifdef(const Token &MacroNameTok) { + First->Ifdef(MacroNameTok); + Second->Ifdef(MacroNameTok); + } + + /// Ifndef -- This hook is called whenever an #ifndef is seen. + virtual void Ifndef(const Token &MacroNameTok) { + First->Ifndef(MacroNameTok); + Second->Ifndef(MacroNameTok); } - virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) { - First->MacroDefined(II, MI); - Second->MacroDefined(II, MI); + /// Else -- This hook is called whenever an #else is seen. + virtual void Else() { + First->Else(); + Second->Else(); } - virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II, - const MacroInfo *MI) { - First->MacroUndefined(Loc, II, MI); - Second->MacroUndefined(Loc, II, MI); + /// Endif -- This hook is called whenever an #endif is seen. + virtual void Endif() { + First->Endif(); + Second->Endif(); } }; diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index 5e8a4f1..094b7ef 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -31,7 +31,7 @@ namespace clang { class FileEntry; class PTHLexer; class Diagnostic; -class StatSysCallCache; +class FileSystemStatCache; class PTHManager : public IdentifierInfoLookup { friend class PTHLexer; @@ -128,11 +128,11 @@ public: /// It is the responsibility of the caller to 'delete' the returned object. PTHLexer *CreateLexer(FileID FID); - /// createStatCache - Returns a StatSysCallCache object for use with + /// createStatCache - Returns a FileSystemStatCache object for use with /// FileManager objects. These objects use the PTH data to speed up /// calls to stat by memoizing their results from when the PTH file /// was generated. - StatSysCallCache *createStatCache(); + FileSystemStatCache *createStatCache(); }; } // end namespace clang diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index c68555b..8bd2236 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -25,6 +25,28 @@ namespace clang { class IdentifierInfo; class PragmaNamespace; + /** + * \brief Describes how the pragma was introduced, e.g., with #pragma, + * _Pragma, or __pragma. + */ + enum PragmaIntroducerKind { + /** + * \brief The pragma was introduced via #pragma. + */ + PIK_HashPragma, + + /** + * \brief The pragma was introduced via the C99 _Pragma(string-literal). + */ + PIK__Pragma, + + /** + * \brief The pragma was introduced via the Microsoft + * __pragma(token-string). + */ + PIK___pragma + }; + /// PragmaHandler - Instances of this interface defined to handle the various /// pragmas that the language front-end uses. Each handler optionally has a /// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with @@ -42,7 +64,8 @@ public: virtual ~PragmaHandler(); llvm::StringRef getName() const { return Name; } - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken) = 0; + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) = 0; /// getIfNamespace - If this is a namespace, return it. This is equivalent to /// using a dynamic_cast, but doesn't require RTTI. @@ -55,7 +78,8 @@ class EmptyPragmaHandler : public PragmaHandler { public: EmptyPragmaHandler(); - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); }; /// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas, @@ -90,7 +114,8 @@ public: return Handlers.empty(); } - virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); virtual PragmaNamespace *getIfNamespace() { return this; } }; diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index 730f04f..afd7ae1 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -35,6 +35,7 @@ void operator delete(void* ptr, clang::PreprocessingRecord& PR, namespace clang { class MacroDefinition; + class FileEntry; /// \brief Base class that describes a preprocessed entity, which may be a /// preprocessor directive or macro instantiation. @@ -54,8 +55,12 @@ namespace clang { /// \brief A macro definition. MacroDefinitionKind, + /// \brief An inclusion directive, such as \c #include, \c + /// #import, or \c #include_next. + InclusionDirectiveKind, + FirstPreprocessingDirective = PreprocessingDirectiveKind, - LastPreprocessingDirective = MacroDefinitionKind + LastPreprocessingDirective = InclusionDirectiveKind }; private: @@ -173,6 +178,66 @@ namespace clang { } static bool classof(const MacroDefinition *) { return true; } }; + + /// \brief Record the location of an inclusion directive, such as an + /// \c #include or \c #import statement. + class InclusionDirective : public PreprocessingDirective { + public: + /// \brief The kind of inclusion directives known to the + /// preprocessor. + enum InclusionKind { + /// \brief An \c #include directive. + Include, + /// \brief An Objective-C \c #import directive. + Import, + /// \brief A GNU \c #include_next directive. + IncludeNext, + /// \brief A Clang \c #__include_macros directive. + IncludeMacros + }; + + private: + /// \brief The name of the file that was included, as written in + /// the source. + llvm::StringRef FileName; + + /// \brief Whether the file name was in quotation marks; otherwise, it was + /// in angle brackets. + unsigned InQuotes : 1; + + /// \brief The kind of inclusion directive we have. + /// + /// This is a value of type InclusionKind. + unsigned Kind : 2; + + /// \brief The file that was included. + const FileEntry *File; + + public: + InclusionDirective(PreprocessingRecord &PPRec, + InclusionKind Kind, llvm::StringRef FileName, + bool InQuotes, const FileEntry *File, SourceRange Range); + + /// \brief Determine what kind of inclusion directive this is. + InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); } + + /// \brief Retrieve the included file name as it was written in the source. + llvm::StringRef getFileName() const { return FileName; } + + /// \brief Determine whether the included file name was written in quotes; + /// otherwise, it was written in angle brackets. + bool wasInQuotes() const { return InQuotes; } + + /// \brief Retrieve the file entry for the actual file that was included + /// by this directive. + const FileEntry *getFile() const { return File; } + + // Implement isa/cast/dyncast/etc. + 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 /// of preprocessing record entries. @@ -183,6 +248,10 @@ namespace clang { /// \brief Read any preallocated preprocessed entities from the external /// source. virtual void ReadPreprocessedEntities() = 0; + + /// \brief Read the preprocessed entity at the given offset. + virtual PreprocessedEntity * + ReadPreprocessedEntityAtOffset(uint64_t Offset) = 0; }; /// \brief A record of the steps taken while preprocessing a source file, @@ -229,13 +298,22 @@ namespace clang { iterator end(bool OnlyLocalEntities = false); const_iterator begin(bool OnlyLocalEntities = false) const; const_iterator end(bool OnlyLocalEntities = false) const; - + /// \brief Add a new preprocessed entity to this record. void addPreprocessedEntity(PreprocessedEntity *Entity); /// \brief Set the external source for preprocessed entities. void SetExternalSource(ExternalPreprocessingRecordSource &Source, unsigned NumPreallocatedEntities); + + /// \brief Retrieve the external source for preprocessed entities. + ExternalPreprocessingRecordSource *getExternalSource() const { + return ExternalSource; + } + + unsigned getNumPreallocatedEntities() const { + return NumPreallocatedEntities; + } /// \brief Set the preallocated entry at the given index to the given /// preprocessed entity. @@ -256,9 +334,14 @@ namespace clang { MacroDefinition *findMacroDefinition(const MacroInfo *MI); virtual void MacroExpands(const Token &Id, const MacroInfo* MI); - virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI); - virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II, - const MacroInfo *MI); + virtual void MacroDefined(const Token &Id, const MacroInfo *MI); + virtual void MacroUndefined(const Token &Id, const MacroInfo *MI); + virtual void InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, + llvm::StringRef FileName, + bool IsAngled, + const FileEntry *File, + SourceLocation EndLoc); }; } // end namespace clang diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 6b9b89e..018f7e9 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSOR_H #define LLVM_CLANG_LEX_PREPROCESSOR_H +#include "clang/Lex/MacroInfo.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/PTHLexer.h" #include "clang/Lex/PPCallbacks.h" @@ -24,6 +25,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" @@ -82,6 +84,7 @@ class Preprocessor { IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_builtin; // __has_builtin + IdentifierInfo *Ident__has_attribute; // __has_attribute IdentifierInfo *Ident__has_include; // __has_include IdentifierInfo *Ident__has_include_next; // __has_include_next @@ -194,10 +197,15 @@ class Preprocessor { /// to the actual definition of the macro. llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros; - /// MICache - A "freelist" of MacroInfo objects that can be reused for quick - /// allocation. - /// FIXME: why not use a singly linked list? - std::vector<MacroInfo*> MICache; + /// \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 + /// deserializing from PCH, we don't need to deserialize identifier & macros + /// just so that we can report that they are unused, we just warn using + /// the SourceLocations of this set (that will be filled by the ASTReader). + /// We are using SmallPtrSet instead of a vector for faster removal. + typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy; + WarnUnusedMacroLocsTy WarnUnusedMacroLocs; /// MacroArgCache - This is a "freelist" of MacroArg objects that can be /// reused for quick allocation. @@ -251,6 +259,22 @@ private: // Cached tokens state. /// invoked (at which point the last position is popped). std::vector<CachedTokensTy::size_type> BacktrackPositions; + struct MacroInfoChain { + MacroInfo MI; + MacroInfoChain *Next; + MacroInfoChain *Prev; + }; + + /// MacroInfos are managed as a chain for easy disposal. This is the head + /// of that list. + MacroInfoChain *MIChainHead; + + /// MICache - A "freelist" of MacroInfo objects that can be reused for quick + /// allocation. + MacroInfoChain *MICache; + + MacroInfo *getInfoForMacro(IdentifierInfo *II) const; + public: Preprocessor(Diagnostic &diags, const LangOptions &opts, const TargetInfo &target, @@ -324,7 +348,10 @@ public: /// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to /// or null if it isn't #define'd. MacroInfo *getMacroInfo(IdentifierInfo *II) const { - return II->hasMacroDefinition() ? Macros.find(II)->second : 0; + if (!II->hasMacroDefinition()) + return 0; + + return getInfoForMacro(II); } /// setMacroInfo - Specify a macro for this identifier. @@ -591,6 +618,9 @@ public: /// for which we are performing code completion. bool isCodeCompletionFile(SourceLocation FileLoc) const; + /// \brief Determine if we are performing code completion. + bool isCodeCompletionEnabled() const { return CodeCompletionFile != 0; } + /// \brief Instruct the preprocessor to skip part of the main /// the main source file. /// @@ -607,12 +637,11 @@ public: /// the specified Token's location, translating the token's start /// position in the current buffer into a SourcePosition object for rendering. DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { - return Diags->Report(FullSourceLoc(Loc, getSourceManager()), DiagID); + return Diags->Report(Loc, DiagID); } DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) { - return Diags->Report(FullSourceLoc(Tok.getLocation(), getSourceManager()), - DiagID); + return Diags->Report(Tok.getLocation(), DiagID); } /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a @@ -622,17 +651,9 @@ public: /// UCNs, etc. /// /// \param Invalid If non-NULL, will be set \c true if an error occurs. - std::string getSpelling(const Token &Tok, bool *Invalid = 0) const; - - /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a - /// token is the characters used to represent the token in the source file - /// after trigraph expansion and escaped-newline folding. In particular, this - /// wants to get the true, uncanonicalized, spelling of things like digraphs - /// UCNs, etc. - static std::string getSpelling(const Token &Tok, - const SourceManager &SourceMgr, - const LangOptions &Features, - bool *Invalid = 0); + std::string getSpelling(const Token &Tok, bool *Invalid = 0) const { + return Lexer::getSpelling(Tok, SourceMgr, Features, Invalid); + } /// getSpelling - This method is used to get the spelling of a token into a /// preallocated buffer, instead of as an std::string. The caller is required @@ -645,7 +666,9 @@ public: /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. unsigned getSpelling(const Token &Tok, const char *&Buffer, - bool *Invalid = 0) const; + bool *Invalid = 0) const { + return Lexer::getSpelling(Tok, Buffer, SourceMgr, Features, Invalid); + } /// getSpelling - This method is used to get the spelling of a token into a /// SmallVector. Note that the returned StringRef may not point to the @@ -692,7 +715,9 @@ public: /// location should refer to. The default offset (0) produces a source /// location pointing just past the end of the token; an offset of 1 produces /// a source location pointing to the last character in the token, etc. - SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0); + SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0) { + return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, Features); + } /// DumpToken - Print the token to stderr, used for debugging. /// @@ -702,7 +727,10 @@ public: /// AdvanceToTokenCharacter - Given a location that specifies the start of a /// token, return a new location that specifies a character within the token. - SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,unsigned Char); + SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, + unsigned Char) const { + return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, Features); + } /// IncrementPasteCounter - Increment the counters for the number of token /// paste operations performed. If fast was specified, this is a 'fast paste' @@ -726,10 +754,10 @@ public: // Preprocessor callback methods. These are invoked by a lexer as various // directives and events are found. - /// LookUpIdentifierInfo - Given a tok::identifier token, look up the - /// identifier information for the token and install it into the token. - IdentifierInfo *LookUpIdentifierInfo(Token &Identifier, - const char *BufPtr = 0) const; + /// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the + /// identifier information for the token and install it into the token, + /// updating the token kind accordingly. + IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const; /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier and has filled in the tokens IdentifierInfo member. This @@ -812,7 +840,12 @@ public: /// This code concatenates and consumes tokens up to the '>' token. It /// returns false if the > was found, otherwise it returns true if it finds /// and consumes the EOM marker. - bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer); + bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer, + SourceLocation &End); + + /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is + /// followed by EOM. Return true if the token is not a valid on-off-switch. + bool LexOnOffSwitch(tok::OnOffSwitch &OOS); private: @@ -909,8 +942,8 @@ private: /// is not enclosed within a string literal. void HandleMicrosoft__pragma(Token &Tok); - void Handle_Pragma(const std::string &StrVal, SourceLocation PragmaLoc, - SourceLocation RParenLoc); + void Handle_Pragma(unsigned Introducer, const std::string &StrVal, + SourceLocation PragmaLoc, SourceLocation RParenLoc); /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and /// start lexing tokens from it instead of the current buffer. @@ -961,12 +994,13 @@ private: void HandleIdentSCCSDirective(Token &Tok); // File inclusion. - void HandleIncludeDirective(Token &Tok, + void HandleIncludeDirective(SourceLocation HashLoc, + Token &Tok, const DirectoryLookup *LookupFrom = 0, bool isImport = false); - void HandleIncludeNextDirective(Token &Tok); - void HandleIncludeMacrosDirective(Token &Tok); - void HandleImportDirective(Token &Tok); + void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok); + void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok); + void HandleImportDirective(SourceLocation HashLoc, Token &Tok); // Macro handling. void HandleDefineDirective(Token &Tok); @@ -981,7 +1015,7 @@ private: void HandleElifDirective(Token &Tok); // Pragmas. - void HandlePragmaDirective(); + void HandlePragmaDirective(unsigned Introducer); public: void HandlePragmaOnce(Token &OnceTok); void HandlePragmaMark(); @@ -997,6 +1031,10 @@ public: // Return true and store the first token only if any CommentHandler // has inserted some tokens and getCommentRetentionState() is false. bool HandleComment(Token &Token, SourceRange Comment); + + /// \brief A macro is used, update information about macros that need unused + /// warnings. + void markMacroAsUsed(MacroInfo *MI); }; /// \brief Abstract base class that describes a handler that will receive diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index 477a213..d833293 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -155,6 +155,18 @@ public: /// getFileEntry - Return the FileEntry corresponding to this FileID. Like /// getFileID(), this only works for lexers with attached preprocessors. const FileEntry *getFileEntry() const; + + /// \brief Iterator that traverses the current stack of preprocessor + /// conditional directives (#if/#ifdef/#ifndef). + typedef llvm::SmallVectorImpl<PPConditionalInfo>::const_iterator + conditional_iterator; + + conditional_iterator conditional_begin() const { + return ConditionalStack.begin(); + } + conditional_iterator conditional_end() const { + return ConditionalStack.end(); + } }; } // end namespace clang diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 954b36e..edcfcc10d 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -76,7 +76,8 @@ public: StartOfLine = 0x01, // At start of line or only after whitespace. LeadingSpace = 0x02, // Whitespace exists before this token. DisableExpand = 0x04, // This identifier may never be macro expanded. - NeedsCleaning = 0x08 // Contained an escaped newline or trigraph. + NeedsCleaning = 0x08, // Contained an escaped newline or trigraph. + LeadingEmptyMacro = 0x10 // Empty macro exists before this token. }; tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } @@ -87,6 +88,12 @@ public: bool is(tok::TokenKind K) const { return Kind == (unsigned) K; } bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; } + /// isAnyIdentifier - 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); + } + /// isLiteral - Return true if this is a "literal", like a numeric /// constant, string, etc. bool isLiteral() const { @@ -96,9 +103,11 @@ public: } bool isAnnotation() const { - return is(tok::annot_typename) || - is(tok::annot_cxxscope) || - is(tok::annot_template_id); +#define ANNOTATION(NAME) \ + if (is(tok::annot_##NAME)) \ + return true; +#include "clang/Basic/TokenKinds.def" + return false; } /// getLocation - Return a source location identifier for the specified @@ -153,7 +162,10 @@ public: } IdentifierInfo *getIdentifierInfo() const { - assert(!isAnnotation() && "Used IdentInfo on annotation token!"); + assert(isNot(tok::raw_identifier) && + "getIdentifierInfo() on a tok::raw_identifier token!"); + assert(!isAnnotation() && + "getIdentifierInfo() on an annotation token!"); if (isLiteral()) return 0; return (IdentifierInfo*) PtrData; } @@ -161,6 +173,18 @@ public: PtrData = (void*) II; } + /// getRawIdentifierData - For a raw identifier token (i.e., an identifier + /// lexed in raw mode), returns a pointer to the start of it in the text + /// buffer if known, null otherwise. + const char *getRawIdentifierData() const { + assert(is(tok::raw_identifier)); + return reinterpret_cast<const char*>(PtrData); + } + void setRawIdentifierData(const char *Ptr) { + assert(is(tok::raw_identifier)); + PtrData = const_cast<char*>(Ptr); + } + /// getLiteralData - For a literal token (numeric constant, string, etc), this /// returns a pointer to the start of it in the text buffer if known, null /// otherwise. @@ -231,7 +255,13 @@ public: /// newlines in it. /// bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; } - + + /// \brief Return true if this token has an empty macro before it. + /// + bool hasLeadingEmptyMacro() const { + return (Flags & LeadingEmptyMacro) ? true : false; + } + }; /// PPConditionalInfo - Information about the conditional stack (#if directives) |