ASTUnit.h revision 175c4a9aa61f4449f27b729737e4438684ac6d92
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 <map> 26#include <string> 27#include <vector> 28#include <cassert> 29#include <utility> 30 31namespace llvm { 32 class MemoryBuffer; 33} 34 35namespace clang { 36class ASTContext; 37class CompilerInvocation; 38class Decl; 39class Diagnostic; 40class FileEntry; 41class FileManager; 42class HeaderSearch; 43class Preprocessor; 44class SourceManager; 45class TargetInfo; 46 47using namespace idx; 48 49/// \brief Utility class for loading a ASTContext from a PCH file. 50/// 51class ASTUnit { 52public: 53 typedef std::map<FileID, std::vector<PreprocessedEntity *> > 54 PreprocessedEntitiesByFileMap; 55private: 56 llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; 57 llvm::OwningPtr<FileManager> FileMgr; 58 llvm::OwningPtr<SourceManager> SourceMgr; 59 llvm::OwningPtr<HeaderSearch> HeaderInfo; 60 llvm::OwningPtr<TargetInfo> Target; 61 llvm::OwningPtr<Preprocessor> PP; 62 llvm::OwningPtr<ASTContext> Ctx; 63 64 /// Optional owned invocation, just used to make the invocation used in 65 /// LoadFromCommandLine available. 66 llvm::OwningPtr<CompilerInvocation> Invocation; 67 68 // OnlyLocalDecls - when true, walking this AST should only visit declarations 69 // that come from the AST itself, not from included precompiled headers. 70 // FIXME: This is temporary; eventually, CIndex will always do this. 71 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 The size of the source buffer that we've reserved for the main 129 /// file within the precompiled preamble. 130 unsigned PreambleReservedSize; 131 132 ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT 133 ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT 134 135 explicit ASTUnit(bool MainFileIsAST); 136 137 void CleanTemporaryFiles(); 138 bool Parse(); 139 140 std::pair<llvm::MemoryBuffer *, unsigned> ComputePreamble( 141 CompilerInvocation &Invocation, 142 bool &CreatedBuffer); 143 144 std::pair<llvm::MemoryBuffer *, bool> BuildPrecompiledPreamble(); 145 146public: 147 class ConcurrencyCheck { 148 volatile ASTUnit &Self; 149 150 public: 151 explicit ConcurrencyCheck(ASTUnit &Self) 152 : Self(Self) 153 { 154 assert(Self.ConcurrencyCheckValue == CheckUnlocked && 155 "Concurrent access to ASTUnit!"); 156 Self.ConcurrencyCheckValue = CheckLocked; 157 } 158 159 ~ConcurrencyCheck() { 160 Self.ConcurrencyCheckValue = CheckUnlocked; 161 } 162 }; 163 friend class ConcurrencyCheck; 164 165 ~ASTUnit(); 166 167 bool isMainFileAST() const { return MainFileIsAST; } 168 169 const Diagnostic &getDiagnostics() const { return *Diagnostics; } 170 Diagnostic &getDiagnostics() { return *Diagnostics; } 171 172 const SourceManager &getSourceManager() const { return *SourceMgr; } 173 SourceManager &getSourceManager() { return *SourceMgr; } 174 175 const Preprocessor &getPreprocessor() const { return *PP.get(); } 176 Preprocessor &getPreprocessor() { return *PP.get(); } 177 178 const ASTContext &getASTContext() const { return *Ctx.get(); } 179 ASTContext &getASTContext() { return *Ctx.get(); } 180 181 const FileManager &getFileManager() const { return *FileMgr; } 182 FileManager &getFileManager() { return *FileMgr; } 183 184 const std::string &getOriginalSourceFileName(); 185 const std::string &getPCHFileName(); 186 187 /// \brief Add a temporary file that the ASTUnit depends on. 188 /// 189 /// This file will be erased when the ASTUnit is destroyed. 190 void addTemporaryFile(const llvm::sys::Path &TempFile) { 191 TemporaryFiles.push_back(TempFile); 192 } 193 194 bool getOnlyLocalDecls() const { return OnlyLocalDecls; } 195 196 void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } 197 ASTLocation getLastASTLocation() const { return LastLoc; } 198 199 std::vector<Decl*> &getTopLevelDecls() { 200 assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); 201 return TopLevelDecls; 202 } 203 const std::vector<Decl*> &getTopLevelDecls() const { 204 assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); 205 return TopLevelDecls; 206 } 207 208 /// \brief Retrieve the mapping from File IDs to the preprocessed entities 209 /// within that file. 210 PreprocessedEntitiesByFileMap &getPreprocessedEntitiesByFile() { 211 return PreprocessedEntitiesByFile; 212 } 213 214 // Retrieve the diagnostics associated with this AST 215 typedef const StoredDiagnostic *stored_diag_iterator; 216 stored_diag_iterator stored_diag_begin() const { 217 return StoredDiagnostics.begin(); 218 } 219 stored_diag_iterator stored_diag_end() const { 220 return StoredDiagnostics.end(); 221 } 222 unsigned stored_diag_size() const { return StoredDiagnostics.size(); } 223 224 llvm::SmallVector<StoredDiagnostic, 4> &getStoredDiagnostics() { 225 return StoredDiagnostics; 226 } 227 228 /// \brief A mapping from a file name to the memory buffer that stores the 229 /// remapped contents of that file. 230 typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile; 231 232 /// \brief Create a ASTUnit from a PCH file. 233 /// 234 /// \param Filename - The PCH file to load. 235 /// 236 /// \param Diags - The diagnostics engine to use for reporting errors; its 237 /// lifetime is expected to extend past that of the returned ASTUnit. 238 /// 239 /// \returns - The initialized ASTUnit or null if the PCH failed to load. 240 static ASTUnit *LoadFromPCHFile(const std::string &Filename, 241 llvm::IntrusiveRefCntPtr<Diagnostic> Diags, 242 bool OnlyLocalDecls = false, 243 RemappedFile *RemappedFiles = 0, 244 unsigned NumRemappedFiles = 0, 245 bool CaptureDiagnostics = false); 246 247 /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a 248 /// CompilerInvocation object. 249 /// 250 /// \param CI - The compiler invocation to use; it must have exactly one input 251 /// source file. The ASTUnit takes ownership of the CompilerInvocation object. 252 /// 253 /// \param Diags - The diagnostics engine to use for reporting errors; its 254 /// lifetime is expected to extend past that of the returned ASTUnit. 255 // 256 // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we 257 // shouldn't need to specify them at construction time. 258 static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, 259 llvm::IntrusiveRefCntPtr<Diagnostic> Diags, 260 bool OnlyLocalDecls = false, 261 bool CaptureDiagnostics = false, 262 bool PrecompilePreamble = false); 263 264 /// LoadFromCommandLine - Create an ASTUnit from a vector of command line 265 /// arguments, which must specify exactly one source file. 266 /// 267 /// \param ArgBegin - The beginning of the argument vector. 268 /// 269 /// \param ArgEnd - The end of the argument vector. 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 /// \param ResourceFilesPath - The path to the compiler resource files. 275 // 276 // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we 277 // shouldn't need to specify them at construction time. 278 static ASTUnit *LoadFromCommandLine(const char **ArgBegin, 279 const char **ArgEnd, 280 llvm::IntrusiveRefCntPtr<Diagnostic> Diags, 281 llvm::StringRef ResourceFilesPath, 282 bool OnlyLocalDecls = false, 283 RemappedFile *RemappedFiles = 0, 284 unsigned NumRemappedFiles = 0, 285 bool CaptureDiagnostics = false, 286 bool PrecompilePreamble = false); 287 288 /// \brief Reparse the source files using the same command-line options that 289 /// were originally used to produce this translation unit. 290 /// 291 /// \returns True if a failure occurred that causes the ASTUnit not to 292 /// contain any translation-unit information, false otherwise. 293 bool Reparse(RemappedFile *RemappedFiles = 0, 294 unsigned NumRemappedFiles = 0); 295}; 296 297} // namespace clang 298 299#endif 300