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