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