1//===--- ExternalASTMerger.h - Merging External AST Interface ---*- 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// This file declares the ExternalASTMerger, which vends a combination of ASTs 11// from several different ASTContext/FileManager pairs 12// 13//===----------------------------------------------------------------------===// 14#ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H 15#define LLVM_CLANG_AST_EXTERNALASTMERGER_H 16 17#include "clang/AST/ASTImporter.h" 18#include "clang/AST/ExternalASTSource.h" 19#include "llvm/Support/raw_ostream.h" 20 21namespace clang { 22 23/// ExternalASTSource implementation that merges information from several 24/// ASTContexts. 25/// 26/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import 27/// (potentially incomplete) Decls and DeclContexts from the source ASTContexts 28/// in response to ExternalASTSource API calls. 29/// 30/// When lookup occurs in the resulting imported DeclContexts, the original 31/// DeclContexts need to be queried. Roughly, there are three cases here: 32/// 33/// - The DeclContext of origin can be found by simple name lookup. In this 34/// case, no additional state is required. 35/// 36/// - The DeclContext of origin is different from what would be found by name 37/// lookup. In this case, Origins contains an entry overriding lookup and 38/// specifying the correct pair of DeclContext/ASTContext. 39/// 40/// - The DeclContext of origin was determined by another ExterenalASTMerger. 41/// (This is possible when the source ASTContext for one of the Importers has 42/// its own ExternalASTMerger). The origin must be properly forwarded in this 43/// case. 44/// 45/// ExternalASTMerger's job is to maintain the data structures necessary to 46/// allow this. The data structures themselves can be extracted (read-only) and 47/// copied for re-use. 48class ExternalASTMerger : public ExternalASTSource { 49public: 50 /// A single origin for a DeclContext. Unlike Decls, DeclContexts do 51 /// not allow their containing ASTContext to be determined in all cases. 52 struct DCOrigin { 53 DeclContext *DC; 54 ASTContext *AST; 55 }; 56 57 typedef std::map<const DeclContext *, DCOrigin> OriginMap; 58 typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector; 59private: 60 /// One importer exists for each source. 61 ImporterVector Importers; 62 /// Overrides in case name lookup would return nothing or would return 63 /// the wrong thing. 64 OriginMap Origins; 65 /// The installed log stream. 66 llvm::raw_ostream *LogStream; 67 68public: 69 /// The target for an ExternalASTMerger. 70 /// 71 /// ASTImporters require both ASTContext and FileManager to be able to 72 /// import SourceLocations properly. 73 struct ImporterTarget { 74 ASTContext &AST; 75 FileManager &FM; 76 }; 77 /// A source for an ExternalASTMerger. 78 /// 79 /// ASTImporters require both ASTContext and FileManager to be able to 80 /// import SourceLocations properly. Additionally, when import occurs for 81 /// a DeclContext whose origin has been overridden, then this 82 /// ExternalASTMerger must be able to determine that. 83 struct ImporterSource { 84 ASTContext &AST; 85 FileManager &FM; 86 const OriginMap &OM; 87 }; 88 89private: 90 /// The target for this ExtenralASTMerger. 91 ImporterTarget Target; 92 93public: 94 ExternalASTMerger(const ImporterTarget &Target, 95 llvm::ArrayRef<ImporterSource> Sources); 96 97 /// Add a set of ASTContexts as possible origins. 98 /// 99 /// Usually the set will be initialized in the constructor, but long-lived 100 /// ExternalASTMergers may neeed to import from new sources (for example, 101 /// newly-parsed source files). 102 /// 103 /// Ensures that Importers does not gain duplicate entries as a result. 104 void AddSources(llvm::ArrayRef<ImporterSource> Sources); 105 106 /// Remove a set of ASTContexts as possible origins. 107 /// 108 /// Sometimes an origin goes away (for example, if a source file gets 109 /// superseded by a newer version). 110 /// 111 /// The caller is responsible for ensuring that this doesn't leave 112 /// DeclContexts that can't be completed. 113 void RemoveSources(llvm::ArrayRef<ImporterSource> Sources); 114 115 /// Implementation of the ExternalASTSource API. 116 bool FindExternalVisibleDeclsByName(const DeclContext *DC, 117 DeclarationName Name) override; 118 119 /// Implementation of the ExternalASTSource API. 120 void 121 FindExternalLexicalDecls(const DeclContext *DC, 122 llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, 123 SmallVectorImpl<Decl *> &Result) override; 124 125 /// Implementation of the ExternalASTSource API. 126 void CompleteType(TagDecl *Tag) override; 127 128 /// Implementation of the ExternalASTSource API. 129 void CompleteType(ObjCInterfaceDecl *Interface) override; 130 131 /// Returns true if DC can be found in any source AST context. 132 bool CanComplete(DeclContext *DC); 133 134 /// Records an origin in Origins only if name lookup would find 135 /// something different or nothing at all. 136 void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin); 137 138 /// Regardless of any checks, override the Origin for a DeclContext. 139 void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin); 140 141 /// Get a read-only view of the Origins map, for use in constructing 142 /// an ImporterSource for another ExternalASTMerger. 143 const OriginMap &GetOrigins() { return Origins; } 144 145 /// Returns true if Importers contains an ASTImporter whose source is 146 /// OriginContext. 147 bool HasImporterForOrigin(ASTContext &OriginContext); 148 149 /// Returns a reference to the ASTRImporter from Importers whose origin 150 /// is OriginContext. This allows manual import of ASTs while preserving the 151 /// OriginMap correctly. 152 ASTImporter &ImporterForOrigin(ASTContext &OriginContext); 153 154 /// Sets the current log stream. 155 void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; } 156private: 157 /// Records and origin in Origins. 158 void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, 159 ASTImporter &importer); 160 161 /// Performs an action for every DeclContext that is identified as 162 /// corresponding (either by forced origin or by name lookup) to DC. 163 template <typename CallbackType> 164 void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback); 165 166public: 167 /// Log something if there is a logging callback installed. 168 llvm::raw_ostream &logs() { return *LogStream; } 169 170 /// True if the log stream is not llvm::nulls(); 171 bool LoggingEnabled() { return LogStream != &llvm::nulls(); } 172}; 173 174} // end namespace clang 175 176#endif 177