ASTUnit.h revision 8b96253907c47141af0b7b2a44a368748d006a87
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<FileManager>      FileMgr;
56  llvm::OwningPtr<SourceManager>    SourceMgr;
57  llvm::OwningPtr<HeaderSearch>     HeaderInfo;
58  llvm::OwningPtr<TargetInfo>       Target;
59  llvm::OwningPtr<Preprocessor>     PP;
60  llvm::OwningPtr<ASTContext>       Ctx;
61
62  /// Optional owned invocation, just used to make the invocation used in
63  /// LoadFromCommandLine available.
64  llvm::OwningPtr<CompilerInvocation> Invocation;
65
66  // OnlyLocalDecls - when true, walking this AST should only visit declarations
67  // that come from the AST itself, not from included precompiled headers.
68  // FIXME: This is temporary; eventually, CIndex will always do this.
69  bool                              OnlyLocalDecls;
70
71  /// Track whether the main file was loaded from an AST or not.
72  bool MainFileIsAST;
73
74  /// Track the top-level decls which appeared in an ASTUnit which was loaded
75  /// from a source file.
76  //
77  // FIXME: This is just an optimization hack to avoid deserializing large parts
78  // of a PCH file when using the Index library on an ASTUnit loaded from
79  // source. In the long term we should make the Index library use efficient and
80  // more scalable search mechanisms.
81  std::vector<Decl*> TopLevelDecls;
82
83  /// The name of the original source file used to generate this ASTUnit.
84  std::string OriginalSourceFile;
85
86  // Critical optimization when using clang_getCursor().
87  ASTLocation LastLoc;
88
89  /// \brief The set of diagnostics produced when creating this
90  /// translation unit.
91  llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
92
93  /// \brief Temporary files that should be removed when the ASTUnit is
94  /// destroyed.
95  llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles;
96
97  /// \brief A mapping from file IDs to the set of preprocessed entities
98  /// stored in that file.
99  ///
100  /// FIXME: This is just an optimization hack to avoid searching through
101  /// many preprocessed entities during cursor traversal in the CIndex library.
102  /// Ideally, we would just be able to perform a binary search within the
103  /// list of preprocessed entities.
104  PreprocessedEntitiesByFileMap PreprocessedEntitiesByFile;
105
106  /// \brief Simple hack to allow us to assert that ASTUnit is not being
107  /// used concurrently, which is not supported.
108  ///
109  /// Clients should create instances of the ConcurrencyCheck class whenever
110  /// using the ASTUnit in a way that isn't intended to be concurrent, which is
111  /// just about any usage.
112  unsigned int ConcurrencyCheckValue;
113  static const unsigned int CheckLocked = 28573289;
114  static const unsigned int CheckUnlocked = 9803453;
115
116  ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
117  ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
118
119  ASTUnit(Diagnostic &Diag, bool MainFileIsAST);
120
121public:
122  class ConcurrencyCheck {
123    volatile ASTUnit &Self;
124
125  public:
126    explicit ConcurrencyCheck(ASTUnit &Self)
127      : Self(Self)
128    {
129      assert(Self.ConcurrencyCheckValue == CheckUnlocked &&
130             "Concurrent access to ASTUnit!");
131      Self.ConcurrencyCheckValue = CheckLocked;
132    }
133
134    ~ConcurrencyCheck() {
135      Self.ConcurrencyCheckValue = CheckUnlocked;
136    }
137  };
138  friend class ConcurrencyCheck;
139
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