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