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