diff options
author | dim <dim@FreeBSD.org> | 2010-09-17 15:54:40 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2010-09-17 15:54:40 +0000 |
commit | 36c49e3f258dced101949edabd72e9bc3f1dedc4 (patch) | |
tree | 0bbe07708f7571f8b5291f6d7b96c102b7c99dee /include/clang/Frontend/ASTUnit.h | |
parent | fc84956ac8b7cd244ef30e7a4d4d38a58dec5904 (diff) | |
download | FreeBSD-src-36c49e3f258dced101949edabd72e9bc3f1dedc4.zip FreeBSD-src-36c49e3f258dced101949edabd72e9bc3f1dedc4.tar.gz |
Vendor import of clang r114020 (from the release_28 branch):
http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020
Approved by: rpaulo (mentor)
Diffstat (limited to 'include/clang/Frontend/ASTUnit.h')
-rw-r--r-- | include/clang/Frontend/ASTUnit.h | 341 |
1 files changed, 324 insertions, 17 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 9252358..e3fd4b3 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -14,19 +14,26 @@ #ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H #define LLVM_CLANG_FRONTEND_ASTUNIT_H +#include "clang/Index/ASTLocation.h" +#include "clang/Serialization/ASTBitCodes.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/FileManager.h" +#include "clang-c/Index.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" -#include "clang/Basic/FileManager.h" -#include "clang/Index/ASTLocation.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/System/Path.h" +#include "llvm/Support/Timer.h" #include <map> #include <string> #include <vector> #include <cassert> #include <utility> +#include <sys/types.h> namespace llvm { class MemoryBuffer; @@ -34,6 +41,7 @@ namespace llvm { namespace clang { class ASTContext; +class CodeCompleteConsumer; class CompilerInvocation; class Decl; class Diagnostic; @@ -45,13 +53,14 @@ class SourceManager; class TargetInfo; using namespace idx; - -/// \brief Utility class for loading a ASTContext from a PCH file. + +/// \brief Utility class for loading a ASTContext from an AST file. /// class ASTUnit { public: typedef std::map<FileID, std::vector<PreprocessedEntity *> > PreprocessedEntitiesByFileMap; + private: llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; llvm::OwningPtr<FileManager> FileMgr; @@ -61,18 +70,32 @@ private: llvm::OwningPtr<Preprocessor> PP; llvm::OwningPtr<ASTContext> Ctx; + /// \brief The AST consumer that received information about the translation + /// unit as it was parsed or loaded. + llvm::OwningPtr<ASTConsumer> Consumer; + + /// \brief The semantic analysis object used to type-check the translation + /// unit. + llvm::OwningPtr<Sema> TheSema; + /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. llvm::OwningPtr<CompilerInvocation> Invocation; - + // OnlyLocalDecls - when true, walking this AST should only visit declarations // that come from the AST itself, not from included precompiled headers. // FIXME: This is temporary; eventually, CIndex will always do this. bool OnlyLocalDecls; - /// Track whether the main file was loaded from an AST or not. + /// \brief Whether to capture any diagnostics produced. + bool CaptureDiagnostics; + + /// \brief Track whether the main file was loaded from an AST or not. bool MainFileIsAST; + /// \brief Whether this AST represents a complete translation unit. + bool CompleteTranslationUnit; + /// Track the top-level decls which appeared in an ASTUnit which was loaded /// from a source file. // @@ -114,12 +137,189 @@ private: unsigned int ConcurrencyCheckValue; static const unsigned int CheckLocked = 28573289; static const unsigned int CheckUnlocked = 9803453; + + /// \brief Counter that determines when we want to try building a + /// precompiled preamble. + /// + /// If zero, we will never build a precompiled preamble. Otherwise, + /// it's treated as a counter that decrements each time we reparse + /// without the benefit of a precompiled preamble. When it hits 1, + /// we'll attempt to rebuild the precompiled header. This way, if + /// building the precompiled preamble fails, we won't try again for + /// some number of calls. + unsigned PreambleRebuildCounter; + + /// \brief The file in which the precompiled preamble is stored. + std::string PreambleFile; + + /// \brief The contents of the preamble that has been precompiled to + /// \c PreambleFile. + std::vector<char> Preamble; + + /// \brief Whether the preamble ends at the start of a new line. + /// + /// Used to inform the lexer as to whether it's starting at the beginning of + /// a line after skipping the preamble. + bool PreambleEndsAtStartOfLine; + + /// \brief The size of the source buffer that we've reserved for the main + /// file within the precompiled preamble. + unsigned PreambleReservedSize; + + /// \brief Keeps track of the files that were used when computing the + /// preamble, with both their buffer size and their modification time. + /// + /// If any of the files have changed from one compile to the next, + /// the preamble must be thrown away. + llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble; + + /// \brief When non-NULL, this is the buffer used to store the contents of + /// the main file when it has been padded for use with the precompiled + /// preamble. + llvm::MemoryBuffer *SavedMainFileBuffer; + + /// \brief When non-NULL, this is the buffer used to store the + /// contents of the preamble when it has been padded to build the + /// precompiled preamble. + llvm::MemoryBuffer *PreambleBuffer; + + /// \brief The number of warnings that occurred while parsing the preamble. + /// + /// This value will be used to restore the state of the \c Diagnostic object + /// when re-using the precompiled preamble. Note that only the + /// number of warnings matters, since we will not save the preamble + /// when any errors are present. + unsigned NumWarningsInPreamble; + + /// \brief The number of diagnostics that were stored when parsing + /// the precompiled preamble. + /// + /// This value is used to determine how many of the stored + /// diagnostics should be retained when reparsing in the presence of + /// a precompiled preamble. + unsigned NumStoredDiagnosticsInPreamble; + + /// \brief The group of timers associated with this translation unit. + llvm::OwningPtr<llvm::TimerGroup> TimerGroup; + + /// \brief A list of the serialization ID numbers for each of the top-level + /// declarations parsed within the precompiled preamble. + std::vector<serialization::DeclID> TopLevelDeclsInPreamble; + + /// + /// \defgroup CodeCompleteCaching Code-completion caching + /// + /// \{ + /// + + /// \brief Whether we should be caching code-completion results. + bool ShouldCacheCodeCompletionResults; + +public: + /// \brief A cached code-completion result, which may be introduced in one of + /// many different contexts. + struct CachedCodeCompletionResult { + /// \brief The code-completion string corresponding to this completion + /// result. + CodeCompletionString *Completion; + + /// \brief A bitmask that indicates which code-completion contexts should + /// contain this completion result. + /// + /// The bits in the bitmask correspond to the values of + /// CodeCompleteContext::Kind. To map from a completion context kind to a + /// bit, subtract one from the completion context kind and shift 1 by that + /// number of bits. Many completions can occur in several different + /// contexts. + unsigned ShowInContexts; + + /// \brief The priority given to this code-completion result. + unsigned Priority; + + /// \brief The libclang cursor kind corresponding to this code-completion + /// result. + CXCursorKind Kind; + + /// \brief The availability of this code-completion result. + CXAvailabilityKind Availability; + + /// \brief The simplified type class for a non-macro completion result. + SimplifiedTypeClass TypeClass; + + /// \brief The type of a non-macro completion result, stored as a unique + /// integer used by the string map of cached completion types. + /// + /// This value will be zero if the type is not known, or a unique value + /// determined by the formatted type string. Se \c CachedCompletionTypes + /// for more information. + unsigned Type; + }; + + /// \brief Retrieve the mapping from formatted type names to unique type + /// identifiers. + llvm::StringMap<unsigned> &getCachedCompletionTypes() { + return CachedCompletionTypes; + } + +private: + /// \brief The set of cached code-completion results. + std::vector<CachedCodeCompletionResult> CachedCompletionResults; + + /// \brief A mapping from the formatted type name to a unique number for that + /// type, which is used for type equality comparisons. + llvm::StringMap<unsigned> CachedCompletionTypes; + + /// \brief The number of top-level declarations present the last time we + /// cached code-completion results. + /// + /// The value is used to help detect when we should repopulate the global + /// completion cache. + unsigned NumTopLevelDeclsAtLastCompletionCache; + + /// \brief The number of reparses left until we'll consider updating the + /// code-completion cache. + /// + /// This is meant to avoid thrashing during reparsing, by not allowing the + /// code-completion cache to be updated on every reparse. + unsigned CacheCodeCompletionCoolDown; + + /// \brief Bit used by CIndex to mark when a translation unit may be in an + /// inconsistent state, and is not safe to free. + unsigned UnsafeToFree : 1; + + /// \brief Cache any "global" code-completion results, so that we can avoid + /// recomputing them with each completion. + void CacheCodeCompletionResults(); + + /// \brief Clear out and deallocate + void ClearCachedCompletionResults(); + + /// + /// \} + /// + + /// \brief The timers we've created from the various parses, reparses, etc. + /// involved in this translation unit. + std::vector<llvm::Timer *> Timers; ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT explicit ASTUnit(bool MainFileIsAST); + void CleanTemporaryFiles(); + bool Parse(llvm::MemoryBuffer *OverrideMainBuffer); + + std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > + ComputePreamble(CompilerInvocation &Invocation, + unsigned MaxLines, bool &CreatedBuffer); + + llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble( + CompilerInvocation PreambleInvocation, + bool AllowRebuild = true, + unsigned MaxLines = 0); + void RealizeTopLevelDeclsFromPreamble(); + public: class ConcurrencyCheck { volatile ASTUnit &Self; @@ -143,6 +343,9 @@ public: bool isMainFileAST() const { return MainFileIsAST; } + bool isUnsafeToFree() const { return UnsafeToFree; } + void setUnsafeToFree(bool Value) { UnsafeToFree = Value; } + const Diagnostic &getDiagnostics() const { return *Diagnostics; } Diagnostic &getDiagnostics() { return *Diagnostics; } @@ -155,11 +358,17 @@ public: const ASTContext &getASTContext() const { return *Ctx.get(); } ASTContext &getASTContext() { return *Ctx.get(); } + bool hasSema() const { return TheSema; } + Sema &getSema() const { + assert(TheSema && "ASTUnit does not have a Sema object!"); + return *TheSema; + } + const FileManager &getFileManager() const { return *FileMgr; } FileManager &getFileManager() { return *FileMgr; } const std::string &getOriginalSourceFileName(); - const std::string &getPCHFileName(); + const std::string &getASTFileName(); /// \brief Add a temporary file that the ASTUnit depends on. /// @@ -170,16 +379,48 @@ public: bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + /// \brief Retrieve the maximum PCH level of declarations that a + /// traversal of the translation unit should consider. + unsigned getMaxPCHLevel() const; + void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } ASTLocation getLastASTLocation() const { return LastLoc; } - std::vector<Decl*> &getTopLevelDecls() { + typedef std::vector<Decl *>::iterator top_level_iterator; + + top_level_iterator top_level_begin() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + if (!TopLevelDeclsInPreamble.empty()) + RealizeTopLevelDeclsFromPreamble(); + return TopLevelDecls.begin(); + } + + top_level_iterator top_level_end() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + if (!TopLevelDeclsInPreamble.empty()) + RealizeTopLevelDeclsFromPreamble(); + return TopLevelDecls.end(); + } + + std::size_t top_level_size() const { assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); - return TopLevelDecls; + return TopLevelDeclsInPreamble.size() + TopLevelDecls.size(); } - const std::vector<Decl*> &getTopLevelDecls() const { + + bool top_level_empty() const { assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); - return TopLevelDecls; + return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty(); + } + + /// \brief Add a new top-level declaration. + void addTopLevelDecl(Decl *D) { + TopLevelDecls.push_back(D); + } + + /// \brief Add a new top-level declaration, identified by its ID in + /// the precompiled preamble. + void addTopLevelDeclFromPreamble(serialization::DeclID D) { + TopLevelDeclsInPreamble.push_back(D); } /// \brief Retrieve the mapping from File IDs to the preprocessed entities @@ -202,19 +443,40 @@ public: return StoredDiagnostics; } + typedef std::vector<CachedCodeCompletionResult>::iterator + cached_completion_iterator; + + cached_completion_iterator cached_completion_begin() { + return CachedCompletionResults.begin(); + } + + cached_completion_iterator cached_completion_end() { + return CachedCompletionResults.end(); + } + + unsigned cached_completion_size() const { + return CachedCompletionResults.size(); + } + + /// \brief Whether this AST represents a complete translation unit. + /// + /// If false, this AST is only a partial translation unit, e.g., one + /// that might still be used as a precompiled header or preamble. + bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; } + /// \brief A mapping from a file name to the memory buffer that stores the /// remapped contents of that file. typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile; - /// \brief Create a ASTUnit from a PCH file. + /// \brief Create a ASTUnit from an AST file. /// - /// \param Filename - The PCH file to load. + /// \param Filename - The AST file to load. /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// - /// \returns - The initialized ASTUnit or null if the PCH failed to load. - static ASTUnit *LoadFromPCHFile(const std::string &Filename, + /// \returns - The initialized ASTUnit or null if the AST failed to load. + static ASTUnit *LoadFromASTFile(const std::string &Filename, llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, @@ -235,7 +497,10 @@ public: static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls = false, - bool CaptureDiagnostics = false); + bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, + bool CompleteTranslationUnit = true, + bool CacheCodeCompletionResults = false); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -258,7 +523,49 @@ public: bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, - bool CaptureDiagnostics = false); + bool CaptureDiagnostics = false, + bool PrecompilePreamble = false, + bool CompleteTranslationUnit = true, + bool CacheCodeCompletionResults = false); + + /// \brief Reparse the source files using the same command-line options that + /// were originally used to produce this translation unit. + /// + /// \returns True if a failure occurred that causes the ASTUnit not to + /// contain any translation-unit information, false otherwise. + bool Reparse(RemappedFile *RemappedFiles = 0, + unsigned NumRemappedFiles = 0); + + /// \brief Perform code completion at the given file, line, and + /// column within this translation unit. + /// + /// \param File The file in which code completion will occur. + /// + /// \param Line The line at which code completion will occur. + /// + /// \param Column The column at which code completion will occur. + /// + /// \param IncludeMacros Whether to include macros in the code-completion + /// results. + /// + /// \param IncludeCodePatterns Whether to include code patterns (such as a + /// for loop) in the code-completion results. + /// + /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and + /// OwnedBuffers parameters are all disgusting hacks. They will go away. + void CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, + RemappedFile *RemappedFiles, unsigned NumRemappedFiles, + bool IncludeMacros, bool IncludeCodePatterns, + CodeCompleteConsumer &Consumer, + Diagnostic &Diag, LangOptions &LangOpts, + SourceManager &SourceMgr, FileManager &FileMgr, + llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, + llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers); + + /// \brief Save this translation unit to a file with the given name. + /// + /// \returns True if an error occurred, false otherwise. + bool Save(llvm::StringRef File); }; } // namespace clang |