ASTUnit.h revision df95a13ec73d2cdaea79555cb412d767f4963120
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/Index/ASTLocation.h"
18#include "clang/Frontend/PCHBitCodes.h"
19#include "clang/Lex/PreprocessingRecord.h"
20#include "clang/Basic/SourceManager.h"
21#include "clang/Basic/FileManager.h"
22#include "llvm/ADT/IntrusiveRefCntPtr.h"
23#include "llvm/ADT/OwningPtr.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/StringMap.h"
26#include "llvm/System/Path.h"
27#include "llvm/Support/Timer.h"
28#include <map>
29#include <string>
30#include <vector>
31#include <cassert>
32#include <utility>
33#include <sys/types.h>
34
35namespace llvm {
36  class MemoryBuffer;
37}
38
39namespace clang {
40class ASTContext;
41class CodeCompleteConsumer;
42class CompilerInvocation;
43class Decl;
44class Diagnostic;
45class FileEntry;
46class FileManager;
47class HeaderSearch;
48class Preprocessor;
49class SourceManager;
50class TargetInfo;
51
52using namespace idx;
53
54/// \brief Utility class for loading a ASTContext from a PCH file.
55///
56class ASTUnit {
57public:
58  typedef std::map<FileID, std::vector<PreprocessedEntity *> >
59    PreprocessedEntitiesByFileMap;
60private:
61  llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
62  llvm::OwningPtr<FileManager>      FileMgr;
63  llvm::OwningPtr<SourceManager>    SourceMgr;
64  llvm::OwningPtr<HeaderSearch>     HeaderInfo;
65  llvm::OwningPtr<TargetInfo>       Target;
66  llvm::OwningPtr<Preprocessor>     PP;
67  llvm::OwningPtr<ASTContext>       Ctx;
68
69  /// Optional owned invocation, just used to make the invocation used in
70  /// LoadFromCommandLine available.
71  llvm::OwningPtr<CompilerInvocation> Invocation;
72
73  // OnlyLocalDecls - when true, walking this AST should only visit declarations
74  // that come from the AST itself, not from included precompiled headers.
75  // FIXME: This is temporary; eventually, CIndex will always do this.
76  bool                              OnlyLocalDecls;
77
78  /// \brief Whether to capture any diagnostics produced.
79  bool CaptureDiagnostics;
80
81  /// \brief Track whether the main file was loaded from an AST or not.
82  bool MainFileIsAST;
83
84  /// \brief Whether this AST represents a complete translation unit.
85  bool CompleteTranslationUnit;
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  /// \brief Counter that determines when we want to try building a
130  /// precompiled preamble.
131  ///
132  /// If zero, we will never build a precompiled preamble. Otherwise,
133  /// it's treated as a counter that decrements each time we reparse
134  /// without the benefit of a precompiled preamble. When it hits 1,
135  /// we'll attempt to rebuild the precompiled header. This way, if
136  /// building the precompiled preamble fails, we won't try again for
137  /// some number of calls.
138  unsigned PreambleRebuildCounter;
139
140  /// \brief The file in which the precompiled preamble is stored.
141  std::string PreambleFile;
142
143  /// \brief The contents of the preamble that has been precompiled to
144  /// \c PreambleFile.
145  std::vector<char> Preamble;
146
147  /// \brief Whether the preamble ends at the start of a new line.
148  ///
149  /// Used to inform the lexer as to whether it's starting at the beginning of
150  /// a line after skipping the preamble.
151  bool PreambleEndsAtStartOfLine;
152
153  /// \brief The size of the source buffer that we've reserved for the main
154  /// file within the precompiled preamble.
155  unsigned PreambleReservedSize;
156
157  /// \brief Keeps track of the files that were used when computing the
158  /// preamble, with both their buffer size and their modification time.
159  ///
160  /// If any of the files have changed from one compile to the next,
161  /// the preamble must be thrown away.
162  llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble;
163
164  /// \brief When non-NULL, this is the buffer used to store the contents of
165  /// the main file when it has been padded for use with the precompiled
166  /// preamble.
167  llvm::MemoryBuffer *SavedMainFileBuffer;
168
169  /// \brief The number of warnings that occurred while parsing the preamble.
170  ///
171  /// This value will be used to restore the state of the \c Diagnostic object
172  /// when re-using the precompiled preamble. Note that only the
173  /// number of warnings matters, since we will not save the preamble
174  /// when any errors are present.
175  unsigned NumWarningsInPreamble;
176
177  /// \brief The number of diagnostics that were stored when parsing
178  /// the precompiled preamble.
179  ///
180  /// This value is used to determine how many of the stored
181  /// diagnostics should be retained when reparsing in the presence of
182  /// a precompiled preamble.
183  unsigned NumStoredDiagnosticsInPreamble;
184
185  /// \brief The group of timers associated with this translation unit.
186  llvm::OwningPtr<llvm::TimerGroup> TimerGroup;
187
188  /// \brief A list of the PCH ID numbers for each of the top-level
189  /// declarations parsed within the precompiled preamble.
190  std::vector<pch::DeclID> TopLevelDeclsInPreamble;
191
192  /// \brief The timers we've created from the various parses, reparses, etc.
193  /// involved in this translation unit.
194  std::vector<llvm::Timer *> Timers;
195
196  ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
197  ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
198
199  explicit ASTUnit(bool MainFileIsAST);
200
201  void CleanTemporaryFiles();
202  bool Parse(llvm::MemoryBuffer *OverrideMainBuffer);
203
204  std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
205  ComputePreamble(CompilerInvocation &Invocation,
206                  unsigned MaxLines, bool &CreatedBuffer);
207
208  llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble(
209                                                     bool AllowRebuild = true,
210                                                        unsigned MaxLines = 0);
211  void RealizeTopLevelDeclsFromPreamble();
212
213public:
214  class ConcurrencyCheck {
215    volatile ASTUnit &Self;
216
217  public:
218    explicit ConcurrencyCheck(ASTUnit &Self)
219      : Self(Self)
220    {
221      assert(Self.ConcurrencyCheckValue == CheckUnlocked &&
222             "Concurrent access to ASTUnit!");
223      Self.ConcurrencyCheckValue = CheckLocked;
224    }
225
226    ~ConcurrencyCheck() {
227      Self.ConcurrencyCheckValue = CheckUnlocked;
228    }
229  };
230  friend class ConcurrencyCheck;
231
232  ~ASTUnit();
233
234  bool isMainFileAST() const { return MainFileIsAST; }
235
236  const Diagnostic &getDiagnostics() const { return *Diagnostics; }
237  Diagnostic &getDiagnostics()             { return *Diagnostics; }
238
239  const SourceManager &getSourceManager() const { return *SourceMgr; }
240        SourceManager &getSourceManager()       { return *SourceMgr; }
241
242  const Preprocessor &getPreprocessor() const { return *PP.get(); }
243        Preprocessor &getPreprocessor()       { return *PP.get(); }
244
245  const ASTContext &getASTContext() const { return *Ctx.get(); }
246        ASTContext &getASTContext()       { return *Ctx.get(); }
247
248  const FileManager &getFileManager() const { return *FileMgr; }
249        FileManager &getFileManager()       { return *FileMgr; }
250
251  const std::string &getOriginalSourceFileName();
252  const std::string &getPCHFileName();
253
254  /// \brief Add a temporary file that the ASTUnit depends on.
255  ///
256  /// This file will be erased when the ASTUnit is destroyed.
257  void addTemporaryFile(const llvm::sys::Path &TempFile) {
258    TemporaryFiles.push_back(TempFile);
259  }
260
261  bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
262
263  /// \brief Retrieve the maximum PCH level of declarations that a
264  /// traversal of the translation unit should consider.
265  unsigned getMaxPCHLevel() const;
266
267  void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
268  ASTLocation getLastASTLocation() const { return LastLoc; }
269
270  typedef std::vector<Decl *>::iterator top_level_iterator;
271
272  top_level_iterator top_level_begin() {
273    assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
274    if (!TopLevelDeclsInPreamble.empty())
275      RealizeTopLevelDeclsFromPreamble();
276    return TopLevelDecls.begin();
277  }
278
279  top_level_iterator top_level_end() {
280    assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
281    if (!TopLevelDeclsInPreamble.empty())
282      RealizeTopLevelDeclsFromPreamble();
283    return TopLevelDecls.end();
284  }
285
286  std::size_t top_level_size() const {
287    assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
288    return TopLevelDeclsInPreamble.size() + TopLevelDecls.size();
289  }
290
291  bool top_level_empty() const {
292    assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
293    return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty();
294  }
295
296  /// \brief Add a new top-level declaration.
297  void addTopLevelDecl(Decl *D) {
298    TopLevelDecls.push_back(D);
299  }
300
301  /// \brief Add a new top-level declaration, identified by its ID in
302  /// the precompiled preamble.
303  void addTopLevelDeclFromPreamble(pch::DeclID D) {
304    TopLevelDeclsInPreamble.push_back(D);
305  }
306
307  /// \brief Retrieve the mapping from File IDs to the preprocessed entities
308  /// within that file.
309  PreprocessedEntitiesByFileMap &getPreprocessedEntitiesByFile() {
310    return PreprocessedEntitiesByFile;
311  }
312
313  // Retrieve the diagnostics associated with this AST
314  typedef const StoredDiagnostic *stored_diag_iterator;
315  stored_diag_iterator stored_diag_begin() const {
316    return StoredDiagnostics.begin();
317  }
318  stored_diag_iterator stored_diag_end() const {
319    return StoredDiagnostics.end();
320  }
321  unsigned stored_diag_size() const { return StoredDiagnostics.size(); }
322
323  llvm::SmallVector<StoredDiagnostic, 4> &getStoredDiagnostics() {
324    return StoredDiagnostics;
325  }
326
327  /// \brief Whether this AST represents a complete translation unit.
328  ///
329  /// If false, this AST is only a partial translation unit, e.g., one
330  /// that might still be used as a precompiled header or preamble.
331  bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; }
332
333  /// \brief A mapping from a file name to the memory buffer that stores the
334  /// remapped contents of that file.
335  typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
336
337  /// \brief Create a ASTUnit from a PCH file.
338  ///
339  /// \param Filename - The PCH file to load.
340  ///
341  /// \param Diags - The diagnostics engine to use for reporting errors; its
342  /// lifetime is expected to extend past that of the returned ASTUnit.
343  ///
344  /// \returns - The initialized ASTUnit or null if the PCH failed to load.
345  static ASTUnit *LoadFromPCHFile(const std::string &Filename,
346                                  llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
347                                  bool OnlyLocalDecls = false,
348                                  RemappedFile *RemappedFiles = 0,
349                                  unsigned NumRemappedFiles = 0,
350                                  bool CaptureDiagnostics = false);
351
352  /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
353  /// CompilerInvocation object.
354  ///
355  /// \param CI - The compiler invocation to use; it must have exactly one input
356  /// source file. The ASTUnit takes ownership of the CompilerInvocation object.
357  ///
358  /// \param Diags - The diagnostics engine to use for reporting errors; its
359  /// lifetime is expected to extend past that of the returned ASTUnit.
360  //
361  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
362  // shouldn't need to specify them at construction time.
363  static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI,
364                                     llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
365                                             bool OnlyLocalDecls = false,
366                                             bool CaptureDiagnostics = false,
367                                             bool PrecompilePreamble = false,
368                                          bool CompleteTranslationUnit = true);
369
370  /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
371  /// arguments, which must specify exactly one source file.
372  ///
373  /// \param ArgBegin - The beginning of the argument vector.
374  ///
375  /// \param ArgEnd - The end of the argument vector.
376  ///
377  /// \param Diags - The diagnostics engine to use for reporting errors; its
378  /// lifetime is expected to extend past that of the returned ASTUnit.
379  ///
380  /// \param ResourceFilesPath - The path to the compiler resource files.
381  //
382  // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
383  // shouldn't need to specify them at construction time.
384  static ASTUnit *LoadFromCommandLine(const char **ArgBegin,
385                                      const char **ArgEnd,
386                                    llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
387                                      llvm::StringRef ResourceFilesPath,
388                                      bool OnlyLocalDecls = false,
389                                      RemappedFile *RemappedFiles = 0,
390                                      unsigned NumRemappedFiles = 0,
391                                      bool CaptureDiagnostics = false,
392                                      bool PrecompilePreamble = false,
393                                      bool CompleteTranslationUnit = true);
394
395  /// \brief Reparse the source files using the same command-line options that
396  /// were originally used to produce this translation unit.
397  ///
398  /// \returns True if a failure occurred that causes the ASTUnit not to
399  /// contain any translation-unit information, false otherwise.
400  bool Reparse(RemappedFile *RemappedFiles = 0,
401               unsigned NumRemappedFiles = 0);
402
403  /// \brief Perform code completion at the given file, line, and
404  /// column within this translation unit.
405  ///
406  /// \param File The file in which code completion will occur.
407  ///
408  /// \param Line The line at which code completion will occur.
409  ///
410  /// \param Column The column at which code completion will occur.
411  ///
412  /// \param IncludeMacros Whether to include macros in the code-completion
413  /// results.
414  ///
415  /// \param IncludeCodePatterns Whether to include code patterns (such as a
416  /// for loop) in the code-completion results.
417  ///
418  /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, and
419  /// StoredDiagnostics parameters are all disgusting hacks. They will
420  /// go away.
421  void CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
422                    RemappedFile *RemappedFiles, unsigned NumRemappedFiles,
423                    bool IncludeMacros, bool IncludeCodePatterns,
424                    CodeCompleteConsumer &Consumer,
425                    Diagnostic &Diag, LangOptions &LangOpts,
426                    SourceManager &SourceMgr, FileManager &FileMgr,
427                    llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics);
428};
429
430} // namespace clang
431
432#endif
433