ASTUnit.h revision f4f6c9db68465b886ec2e596feaa6ecc782395a4
1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===// 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The LLVM Compiler Infrastructure 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// License. See LICENSE.TXT for details. 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)//===----------------------------------------------------------------------===// 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// ASTUnit utility class. 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)//===----------------------------------------------------------------------===// 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#define LLVM_CLANG_FRONTEND_ASTUNIT_H 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "clang/Lex/PreprocessingRecord.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "clang/Basic/SourceManager.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "llvm/ADT/IntrusiveRefCntPtr.h" 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "llvm/ADT/OwningPtr.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "clang/Basic/FileManager.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "clang/Index/ASTLocation.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "llvm/ADT/SmallVector.h" 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "llvm/System/Path.h" 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <map> 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string> 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <vector> 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <cassert> 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <utility> 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace llvm { 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) class MemoryBuffer; 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace clang { 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class ASTContext; 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class CompilerInvocation; 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class Decl; 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Diagnostic; 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class FileEntry; 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class FileManager; 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class HeaderSearch; 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class Preprocessor; 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class SourceManager; 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class TargetInfo; 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using namespace idx; 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/// \brief Utility class for loading a ASTContext from a PCH file. 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class ASTUnit { 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)public: 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef std::map<FileID, std::vector<PreprocessedEntity *> > 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) PreprocessedEntitiesByFileMap; 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)private: 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) llvm::OwningPtr<FileManager> FileMgr; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) llvm::OwningPtr<SourceManager> SourceMgr; 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) llvm::OwningPtr<HeaderSearch> HeaderInfo; 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) llvm::OwningPtr<TargetInfo> Target; 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) llvm::OwningPtr<Preprocessor> PP; 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) llvm::OwningPtr<ASTContext> Ctx; 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /// Optional owned invocation, just used to make the invocation used in 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /// LoadFromCommandLine available. 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) llvm::OwningPtr<CompilerInvocation> Invocation; 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // OnlyLocalDecls - when true, walking this AST should only visit declarations 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // that come from the AST itself, not from included precompiled headers. 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // FIXME: This is temporary; eventually, CIndex will always do this. 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool OnlyLocalDecls; 72 73 /// \brief Whether to capture any diagnostics produced. 74 bool CaptureDiagnostics; 75 76 /// Track whether the main file was loaded from an AST or not. 77 bool MainFileIsAST; 78 79 /// Track the top-level decls which appeared in an ASTUnit which was loaded 80 /// from a source file. 81 // 82 // FIXME: This is just an optimization hack to avoid deserializing large parts 83 // of a PCH file when using the Index library on an ASTUnit loaded from 84 // source. In the long term we should make the Index library use efficient and 85 // more scalable search mechanisms. 86 std::vector<Decl*> TopLevelDecls; 87 88 /// The name of the original source file used to generate this ASTUnit. 89 std::string OriginalSourceFile; 90 91 // Critical optimization when using clang_getCursor(). 92 ASTLocation LastLoc; 93 94 /// \brief The set of diagnostics produced when creating this 95 /// translation unit. 96 llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics; 97 98 /// \brief Temporary files that should be removed when the ASTUnit is 99 /// destroyed. 100 llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles; 101 102 /// \brief A mapping from file IDs to the set of preprocessed entities 103 /// stored in that file. 104 /// 105 /// FIXME: This is just an optimization hack to avoid searching through 106 /// many preprocessed entities during cursor traversal in the CIndex library. 107 /// Ideally, we would just be able to perform a binary search within the 108 /// list of preprocessed entities. 109 PreprocessedEntitiesByFileMap PreprocessedEntitiesByFile; 110 111 /// \brief Simple hack to allow us to assert that ASTUnit is not being 112 /// used concurrently, which is not supported. 113 /// 114 /// Clients should create instances of the ConcurrencyCheck class whenever 115 /// using the ASTUnit in a way that isn't intended to be concurrent, which is 116 /// just about any usage. 117 unsigned int ConcurrencyCheckValue; 118 static const unsigned int CheckLocked = 28573289; 119 static const unsigned int CheckUnlocked = 9803453; 120 121 /// \brief The file in which the precompiled preamble is stored. 122 llvm::sys::Path PreambleFile; 123 124 /// \brief The contents of the preamble that has been precompiled to 125 /// \c PreambleFile. 126 std::vector<char> Preamble; 127 128 /// \brief Whether the preamble ends at the start of a new line. 129 /// 130 /// Used to inform the lexer as to whether it's starting at the beginning of 131 /// a line after skipping the preamble. 132 bool PreambleEndsAtStartOfLine; 133 134 /// \brief The size of the source buffer that we've reserved for the main 135 /// file within the precompiled preamble. 136 unsigned PreambleReservedSize; 137 138 ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT 139 ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT 140 141 explicit ASTUnit(bool MainFileIsAST); 142 143 void CleanTemporaryFiles(); 144 bool Parse(llvm::MemoryBuffer *OverrideMainBuffer); 145 146 std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > 147 ComputePreamble(CompilerInvocation &Invocation, bool &CreatedBuffer); 148 149 llvm::MemoryBuffer *BuildPrecompiledPreamble(); 150 151public: 152 class ConcurrencyCheck { 153 volatile ASTUnit &Self; 154 155 public: 156 explicit ConcurrencyCheck(ASTUnit &Self) 157 : Self(Self) 158 { 159 assert(Self.ConcurrencyCheckValue == CheckUnlocked && 160 "Concurrent access to ASTUnit!"); 161 Self.ConcurrencyCheckValue = CheckLocked; 162 } 163 164 ~ConcurrencyCheck() { 165 Self.ConcurrencyCheckValue = CheckUnlocked; 166 } 167 }; 168 friend class ConcurrencyCheck; 169 170 ~ASTUnit(); 171 172 bool isMainFileAST() const { return MainFileIsAST; } 173 174 const Diagnostic &getDiagnostics() const { return *Diagnostics; } 175 Diagnostic &getDiagnostics() { return *Diagnostics; } 176 177 const SourceManager &getSourceManager() const { return *SourceMgr; } 178 SourceManager &getSourceManager() { return *SourceMgr; } 179 180 const Preprocessor &getPreprocessor() const { return *PP.get(); } 181 Preprocessor &getPreprocessor() { return *PP.get(); } 182 183 const ASTContext &getASTContext() const { return *Ctx.get(); } 184 ASTContext &getASTContext() { return *Ctx.get(); } 185 186 const FileManager &getFileManager() const { return *FileMgr; } 187 FileManager &getFileManager() { return *FileMgr; } 188 189 const std::string &getOriginalSourceFileName(); 190 const std::string &getPCHFileName(); 191 192 /// \brief Add a temporary file that the ASTUnit depends on. 193 /// 194 /// This file will be erased when the ASTUnit is destroyed. 195 void addTemporaryFile(const llvm::sys::Path &TempFile) { 196 TemporaryFiles.push_back(TempFile); 197 } 198 199 bool getOnlyLocalDecls() const { return OnlyLocalDecls; } 200 201 void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } 202 ASTLocation getLastASTLocation() const { return LastLoc; } 203 204 std::vector<Decl*> &getTopLevelDecls() { 205 assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); 206 return TopLevelDecls; 207 } 208 const std::vector<Decl*> &getTopLevelDecls() const { 209 assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); 210 return TopLevelDecls; 211 } 212 213 /// \brief Retrieve the mapping from File IDs to the preprocessed entities 214 /// within that file. 215 PreprocessedEntitiesByFileMap &getPreprocessedEntitiesByFile() { 216 return PreprocessedEntitiesByFile; 217 } 218 219 // Retrieve the diagnostics associated with this AST 220 typedef const StoredDiagnostic *stored_diag_iterator; 221 stored_diag_iterator stored_diag_begin() const { 222 return StoredDiagnostics.begin(); 223 } 224 stored_diag_iterator stored_diag_end() const { 225 return StoredDiagnostics.end(); 226 } 227 unsigned stored_diag_size() const { return StoredDiagnostics.size(); } 228 229 llvm::SmallVector<StoredDiagnostic, 4> &getStoredDiagnostics() { 230 return StoredDiagnostics; 231 } 232 233 /// \brief A mapping from a file name to the memory buffer that stores the 234 /// remapped contents of that file. 235 typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile; 236 237 /// \brief Create a ASTUnit from a PCH file. 238 /// 239 /// \param Filename - The PCH file to load. 240 /// 241 /// \param Diags - The diagnostics engine to use for reporting errors; its 242 /// lifetime is expected to extend past that of the returned ASTUnit. 243 /// 244 /// \returns - The initialized ASTUnit or null if the PCH failed to load. 245 static ASTUnit *LoadFromPCHFile(const std::string &Filename, 246 llvm::IntrusiveRefCntPtr<Diagnostic> Diags, 247 bool OnlyLocalDecls = false, 248 RemappedFile *RemappedFiles = 0, 249 unsigned NumRemappedFiles = 0, 250 bool CaptureDiagnostics = false); 251 252 /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a 253 /// CompilerInvocation object. 254 /// 255 /// \param CI - The compiler invocation to use; it must have exactly one input 256 /// source file. The ASTUnit takes ownership of the CompilerInvocation object. 257 /// 258 /// \param Diags - The diagnostics engine to use for reporting errors; its 259 /// lifetime is expected to extend past that of the returned ASTUnit. 260 // 261 // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we 262 // shouldn't need to specify them at construction time. 263 static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, 264 llvm::IntrusiveRefCntPtr<Diagnostic> Diags, 265 bool OnlyLocalDecls = false, 266 bool CaptureDiagnostics = false, 267 bool PrecompilePreamble = false); 268 269 /// LoadFromCommandLine - Create an ASTUnit from a vector of command line 270 /// arguments, which must specify exactly one source file. 271 /// 272 /// \param ArgBegin - The beginning of the argument vector. 273 /// 274 /// \param ArgEnd - The end of the argument vector. 275 /// 276 /// \param Diags - The diagnostics engine to use for reporting errors; its 277 /// lifetime is expected to extend past that of the returned ASTUnit. 278 /// 279 /// \param ResourceFilesPath - The path to the compiler resource files. 280 // 281 // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we 282 // shouldn't need to specify them at construction time. 283 static ASTUnit *LoadFromCommandLine(const char **ArgBegin, 284 const char **ArgEnd, 285 llvm::IntrusiveRefCntPtr<Diagnostic> Diags, 286 llvm::StringRef ResourceFilesPath, 287 bool OnlyLocalDecls = false, 288 RemappedFile *RemappedFiles = 0, 289 unsigned NumRemappedFiles = 0, 290 bool CaptureDiagnostics = false, 291 bool PrecompilePreamble = false); 292 293 /// \brief Reparse the source files using the same command-line options that 294 /// were originally used to produce this translation unit. 295 /// 296 /// \returns True if a failure occurred that causes the ASTUnit not to 297 /// contain any translation-unit information, false otherwise. 298 bool Reparse(RemappedFile *RemappedFiles = 0, 299 unsigned NumRemappedFiles = 0); 300}; 301 302} // namespace clang 303 304#endif 305