Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. //  This file declares the ExternalASTMerger, which vends a combination of ASTs
  10. //  from several different ASTContext/FileManager pairs
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
  14. #define LLVM_CLANG_AST_EXTERNALASTMERGER_H
  15.  
  16. #include "clang/AST/ASTImporter.h"
  17. #include "clang/AST/ASTImporterSharedState.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. /// ExternalASTMerger 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 ExternalASTMerger.
  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.   class ImporterSource {
  84.     ASTContext &AST;
  85.     FileManager &FM;
  86.     const OriginMap &OM;
  87.     /// True iff the source only exists temporary, i.e., it will be removed from
  88.     /// the ExternalASTMerger during the life time of the ExternalASTMerger.
  89.     bool Temporary;
  90.     /// If the ASTContext of this source has an ExternalASTMerger that imports
  91.     /// into this source, then this will point to that other ExternalASTMerger.
  92.     ExternalASTMerger *Merger;
  93.  
  94.   public:
  95.     ImporterSource(ASTContext &AST, FileManager &FM, const OriginMap &OM,
  96.                    bool Temporary = false, ExternalASTMerger *Merger = nullptr)
  97.         : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {}
  98.     ASTContext &getASTContext() const { return AST; }
  99.     FileManager &getFileManager() const { return FM; }
  100.     const OriginMap &getOriginMap() const { return OM; }
  101.     bool isTemporary() const { return Temporary; }
  102.     ExternalASTMerger *getMerger() const { return Merger; }
  103.   };
  104.  
  105. private:
  106.   /// The target for this ExternalASTMerger.
  107.   ImporterTarget Target;
  108.   /// ExternalASTMerger has multiple ASTImporters that import into the same
  109.   /// TU. This is the shared state for all ASTImporters of this
  110.   /// ExternalASTMerger.
  111.   /// See also the CrossTranslationUnitContext that has a similar setup.
  112.   std::shared_ptr<ASTImporterSharedState> SharedState;
  113.  
  114. public:
  115.   ExternalASTMerger(const ImporterTarget &Target,
  116.                     llvm::ArrayRef<ImporterSource> Sources);
  117.  
  118.   /// Asks all connected ASTImporters if any of them imported the given
  119.   /// declaration. If any ASTImporter did import the given declaration,
  120.   /// then this function returns the declaration that D was imported from.
  121.   /// Returns nullptr if no ASTImporter did import D.
  122.   Decl *FindOriginalDecl(Decl *D);
  123.  
  124.   /// Add a set of ASTContexts as possible origins.
  125.   ///
  126.   /// Usually the set will be initialized in the constructor, but long-lived
  127.   /// ExternalASTMergers may need to import from new sources (for example,
  128.   /// newly-parsed source files).
  129.   ///
  130.   /// Ensures that Importers does not gain duplicate entries as a result.
  131.   void AddSources(llvm::ArrayRef<ImporterSource> Sources);
  132.  
  133.   /// Remove a set of ASTContexts as possible origins.
  134.   ///
  135.   /// Sometimes an origin goes away (for example, if a source file gets
  136.   /// superseded by a newer version).
  137.   ///
  138.   /// The caller is responsible for ensuring that this doesn't leave
  139.   /// DeclContexts that can't be completed.
  140.   void RemoveSources(llvm::ArrayRef<ImporterSource> Sources);
  141.  
  142.   /// Implementation of the ExternalASTSource API.
  143.   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
  144.                                       DeclarationName Name) override;
  145.  
  146.   /// Implementation of the ExternalASTSource API.
  147.   void
  148.   FindExternalLexicalDecls(const DeclContext *DC,
  149.                            llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
  150.                            SmallVectorImpl<Decl *> &Result) override;
  151.  
  152.   /// Implementation of the ExternalASTSource API.
  153.   void CompleteType(TagDecl *Tag) override;
  154.  
  155.   /// Implementation of the ExternalASTSource API.
  156.   void CompleteType(ObjCInterfaceDecl *Interface) override;
  157.  
  158.   /// Returns true if DC can be found in any source AST context.
  159.   bool CanComplete(DeclContext *DC);
  160.  
  161.   /// Records an origin in Origins only if name lookup would find
  162.   /// something different or nothing at all.
  163.   void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
  164.  
  165.   /// Regardless of any checks, override the Origin for a DeclContext.
  166.   void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
  167.  
  168.   /// Get a read-only view of the Origins map, for use in constructing
  169.   /// an ImporterSource for another ExternalASTMerger.
  170.   const OriginMap &GetOrigins() { return Origins; }
  171.  
  172.   /// Returns true if Importers contains an ASTImporter whose source is
  173.   /// OriginContext.
  174.   bool HasImporterForOrigin(ASTContext &OriginContext);
  175.  
  176.   /// Returns a reference to the ASTImporter from Importers whose origin
  177.   /// is OriginContext.  This allows manual import of ASTs while preserving the
  178.   /// OriginMap correctly.
  179.   ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
  180.  
  181.   /// Sets the current log stream.
  182.   void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
  183. private:
  184.   /// Records and origin in Origins.
  185.   void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
  186.                                   ASTImporter &importer);
  187.  
  188.   /// Performs an action for every DeclContext that is identified as
  189.   /// corresponding (either by forced origin or by name lookup) to DC.
  190.   template <typename CallbackType>
  191.   void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);
  192.  
  193. public:
  194.   /// Log something if there is a logging callback installed.
  195.   llvm::raw_ostream &logs() { return *LogStream; }
  196.  
  197.   /// True if the log stream is not llvm::nulls();
  198.   bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
  199. };
  200.  
  201. } // end namespace clang
  202.  
  203. #endif
  204.