Home | History | Annotate | Download | only in AST
      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 
     21 namespace 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.
     48 class ExternalASTMerger : public ExternalASTSource {
     49 public:
     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;
     59 private:
     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 
     68 public:
     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 
     89 private:
     90   /// The target for this ExtenralASTMerger.
     91   ImporterTarget Target;
     92 
     93 public:
     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; }
    156 private:
    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 
    166 public:
    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