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