Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:37

0001 //===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file declares the ExternalASTMerger, which vends a combination of ASTs
0010 //  from several different ASTContext/FileManager pairs
0011 //
0012 //===----------------------------------------------------------------------===//
0013 #ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
0014 #define LLVM_CLANG_AST_EXTERNALASTMERGER_H
0015 
0016 #include "clang/AST/ASTImporter.h"
0017 #include "clang/AST/ASTImporterSharedState.h"
0018 #include "clang/AST/ExternalASTSource.h"
0019 #include "llvm/Support/raw_ostream.h"
0020 
0021 namespace clang {
0022 
0023 /// ExternalASTSource implementation that merges information from several
0024 /// ASTContexts.
0025 ///
0026 /// ExternalASTMerger maintains a vector of ASTImporters that it uses to import
0027 /// (potentially incomplete) Decls and DeclContexts from the source ASTContexts
0028 /// in response to ExternalASTSource API calls.
0029 ///
0030 /// When lookup occurs in the resulting imported DeclContexts, the original
0031 /// DeclContexts need to be queried.  Roughly, there are three cases here:
0032 ///
0033 /// - The DeclContext of origin can be found by simple name lookup.  In this
0034 ///   case, no additional state is required.
0035 ///
0036 /// - The DeclContext of origin is different from what would be found by name
0037 ///   lookup.  In this case, Origins contains an entry overriding lookup and
0038 ///   specifying the correct pair of DeclContext/ASTContext.
0039 ///
0040 /// - The DeclContext of origin was determined by another ExternalASTMerger.
0041 ///   (This is possible when the source ASTContext for one of the Importers has
0042 ///   its own ExternalASTMerger).  The origin must be properly forwarded in this
0043 ///   case.
0044 ///
0045 /// ExternalASTMerger's job is to maintain the data structures necessary to
0046 /// allow this.  The data structures themselves can be extracted (read-only) and
0047 /// copied for re-use.
0048 class ExternalASTMerger : public ExternalASTSource {
0049 public:
0050   /// A single origin for a DeclContext.  Unlike Decls, DeclContexts do
0051   /// not allow their containing ASTContext to be determined in all cases.
0052   struct DCOrigin {
0053     DeclContext *DC;
0054     ASTContext *AST;
0055   };
0056 
0057   typedef std::map<const DeclContext *, DCOrigin> OriginMap;
0058   typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
0059 private:
0060   /// One importer exists for each source.
0061   ImporterVector Importers;
0062   /// Overrides in case name lookup would return nothing or would return
0063   /// the wrong thing.
0064   OriginMap Origins;
0065   /// The installed log stream.
0066   llvm::raw_ostream *LogStream;
0067 
0068 public:
0069   /// The target for an ExternalASTMerger.
0070   ///
0071   /// ASTImporters require both ASTContext and FileManager to be able to
0072   /// import SourceLocations properly.
0073   struct ImporterTarget {
0074     ASTContext &AST;
0075     FileManager &FM;
0076   };
0077   /// A source for an ExternalASTMerger.
0078   ///
0079   /// ASTImporters require both ASTContext and FileManager to be able to
0080   /// import SourceLocations properly.  Additionally, when import occurs for
0081   /// a DeclContext whose origin has been overridden, then this
0082   /// ExternalASTMerger must be able to determine that.
0083   class ImporterSource {
0084     ASTContext &AST;
0085     FileManager &FM;
0086     const OriginMap &OM;
0087     /// True iff the source only exists temporary, i.e., it will be removed from
0088     /// the ExternalASTMerger during the life time of the ExternalASTMerger.
0089     bool Temporary;
0090     /// If the ASTContext of this source has an ExternalASTMerger that imports
0091     /// into this source, then this will point to that other ExternalASTMerger.
0092     ExternalASTMerger *Merger;
0093 
0094   public:
0095     ImporterSource(ASTContext &AST, FileManager &FM, const OriginMap &OM,
0096                    bool Temporary = false, ExternalASTMerger *Merger = nullptr)
0097         : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {}
0098     ASTContext &getASTContext() const { return AST; }
0099     FileManager &getFileManager() const { return FM; }
0100     const OriginMap &getOriginMap() const { return OM; }
0101     bool isTemporary() const { return Temporary; }
0102     ExternalASTMerger *getMerger() const { return Merger; }
0103   };
0104 
0105 private:
0106   /// The target for this ExternalASTMerger.
0107   ImporterTarget Target;
0108   /// ExternalASTMerger has multiple ASTImporters that import into the same
0109   /// TU. This is the shared state for all ASTImporters of this
0110   /// ExternalASTMerger.
0111   /// See also the CrossTranslationUnitContext that has a similar setup.
0112   std::shared_ptr<ASTImporterSharedState> SharedState;
0113 
0114 public:
0115   ExternalASTMerger(const ImporterTarget &Target,
0116                     llvm::ArrayRef<ImporterSource> Sources);
0117 
0118   /// Asks all connected ASTImporters if any of them imported the given
0119   /// declaration. If any ASTImporter did import the given declaration,
0120   /// then this function returns the declaration that D was imported from.
0121   /// Returns nullptr if no ASTImporter did import D.
0122   Decl *FindOriginalDecl(Decl *D);
0123 
0124   /// Add a set of ASTContexts as possible origins.
0125   ///
0126   /// Usually the set will be initialized in the constructor, but long-lived
0127   /// ExternalASTMergers may need to import from new sources (for example,
0128   /// newly-parsed source files).
0129   ///
0130   /// Ensures that Importers does not gain duplicate entries as a result.
0131   void AddSources(llvm::ArrayRef<ImporterSource> Sources);
0132 
0133   /// Remove a set of ASTContexts as possible origins.
0134   ///
0135   /// Sometimes an origin goes away (for example, if a source file gets
0136   /// superseded by a newer version).
0137   ///
0138   /// The caller is responsible for ensuring that this doesn't leave
0139   /// DeclContexts that can't be completed.
0140   void RemoveSources(llvm::ArrayRef<ImporterSource> Sources);
0141 
0142   /// Implementation of the ExternalASTSource API.
0143   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
0144                                       DeclarationName Name,
0145                                       const DeclContext *OriginalDC) override;
0146 
0147   /// Implementation of the ExternalASTSource API.
0148   void
0149   FindExternalLexicalDecls(const DeclContext *DC,
0150                            llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
0151                            SmallVectorImpl<Decl *> &Result) override;
0152 
0153   /// Implementation of the ExternalASTSource API.
0154   void CompleteType(TagDecl *Tag) override;
0155 
0156   /// Implementation of the ExternalASTSource API.
0157   void CompleteType(ObjCInterfaceDecl *Interface) override;
0158 
0159   /// Returns true if DC can be found in any source AST context.
0160   bool CanComplete(DeclContext *DC);
0161 
0162   /// Records an origin in Origins only if name lookup would find
0163   /// something different or nothing at all.
0164   void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
0165 
0166   /// Regardless of any checks, override the Origin for a DeclContext.
0167   void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
0168 
0169   /// Get a read-only view of the Origins map, for use in constructing
0170   /// an ImporterSource for another ExternalASTMerger.
0171   const OriginMap &GetOrigins() { return Origins; }
0172 
0173   /// Returns true if Importers contains an ASTImporter whose source is
0174   /// OriginContext.
0175   bool HasImporterForOrigin(ASTContext &OriginContext);
0176 
0177   /// Returns a reference to the ASTImporter from Importers whose origin
0178   /// is OriginContext.  This allows manual import of ASTs while preserving the
0179   /// OriginMap correctly.
0180   ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
0181 
0182   /// Sets the current log stream.
0183   void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
0184 private:
0185   /// Records and origin in Origins.
0186   void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
0187                                   ASTImporter &importer);
0188 
0189   /// Performs an action for every DeclContext that is identified as
0190   /// corresponding (either by forced origin or by name lookup) to DC.
0191   template <typename CallbackType>
0192   void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);
0193 
0194 public:
0195   /// Log something if there is a logging callback installed.
0196   llvm::raw_ostream &logs() { return *LogStream; }
0197 
0198   /// True if the log stream is not llvm::nulls();
0199   bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
0200 };
0201 
0202 } // end namespace clang
0203 
0204 #endif