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