Home | History | Annotate | Download | only in CrossTU
      1 //===--- CrossTranslationUnit.h - -------------------------------*- 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 provides an interface to load binary AST dumps on demand. This
     11 //  feature can be utilized for tools that require cross translation unit
     12 //  support.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 #ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
     16 #define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
     17 
     18 #include "clang/Basic/LLVM.h"
     19 #include "llvm/ADT/DenseMap.h"
     20 #include "llvm/ADT/SmallPtrSet.h"
     21 #include "llvm/ADT/StringMap.h"
     22 #include "llvm/Support/Error.h"
     23 
     24 namespace clang {
     25 class CompilerInstance;
     26 class ASTContext;
     27 class ASTImporter;
     28 class ASTUnit;
     29 class DeclContext;
     30 class FunctionDecl;
     31 class NamedDecl;
     32 class TranslationUnitDecl;
     33 
     34 namespace cross_tu {
     35 
     36 enum class index_error_code {
     37   unspecified = 1,
     38   missing_index_file,
     39   invalid_index_format,
     40   multiple_definitions,
     41   missing_definition,
     42   failed_import,
     43   failed_to_get_external_ast,
     44   failed_to_generate_usr
     45 };
     46 
     47 class IndexError : public llvm::ErrorInfo<IndexError> {
     48 public:
     49   static char ID;
     50   IndexError(index_error_code C) : Code(C), LineNo(0) {}
     51   IndexError(index_error_code C, std::string FileName, int LineNo = 0)
     52       : Code(C), FileName(std::move(FileName)), LineNo(LineNo) {}
     53   void log(raw_ostream &OS) const override;
     54   std::error_code convertToErrorCode() const override;
     55   index_error_code getCode() const { return Code; }
     56   int getLineNum() const { return LineNo; }
     57   std::string getFileName() const { return FileName; }
     58 
     59 private:
     60   index_error_code Code;
     61   std::string FileName;
     62   int LineNo;
     63 };
     64 
     65 /// \brief This function parses an index file that determines which
     66 ///        translation unit contains which definition.
     67 ///
     68 /// The index file format is the following:
     69 /// each line consists of an USR and a filepath separated by a space.
     70 ///
     71 /// \return Returns a map where the USR is the key and the filepath is the value
     72 ///         or an error.
     73 llvm::Expected<llvm::StringMap<std::string>>
     74 parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir);
     75 
     76 std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index);
     77 
     78 /// \brief This class is used for tools that requires cross translation
     79 ///        unit capability.
     80 ///
     81 /// This class can load function definitions from external AST files.
     82 /// The loaded definition will be merged back to the original AST using the
     83 /// AST Importer.
     84 /// In order to use this class, an index file is required that describes
     85 /// the locations of the AST files for each function definition.
     86 ///
     87 /// Note that this class also implements caching.
     88 class CrossTranslationUnitContext {
     89 public:
     90   CrossTranslationUnitContext(CompilerInstance &CI);
     91   ~CrossTranslationUnitContext();
     92 
     93   /// \brief This function loads a function definition from an external AST
     94   ///        file and merge it into the original AST.
     95   ///
     96   /// This method should only be used on functions that have no definitions in
     97   /// the current translation unit. A function definition with the same
     98   /// declaration will be looked up in the index file which should be in the
     99   /// \p CrossTUDir directory, called \p IndexName. In case the declaration is
    100   /// found in the index the corresponding AST file will be loaded and the
    101   /// definition of the function will be merged into the original AST using
    102   /// the AST Importer.
    103   ///
    104   /// \return The declaration with the definition will be returned.
    105   /// If no suitable definition is found in the index file or multiple
    106   /// definitions found error will be returned.
    107   ///
    108   /// Note that the AST files should also be in the \p CrossTUDir.
    109   llvm::Expected<const FunctionDecl *>
    110   getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir,
    111                        StringRef IndexName);
    112 
    113   /// \brief This function loads a function definition from an external AST
    114   ///        file.
    115   ///
    116   /// A function definition with the same declaration will be looked up in the
    117   /// index file which should be in the \p CrossTUDir directory, called
    118   /// \p IndexName. In case the declaration is found in the index the
    119   /// corresponding AST file will be loaded.
    120   ///
    121   /// \return Returns an ASTUnit that contains the definition of the looked up
    122   /// function.
    123   ///
    124   /// Note that the AST files should also be in the \p CrossTUDir.
    125   llvm::Expected<ASTUnit *> loadExternalAST(StringRef LookupName,
    126                                             StringRef CrossTUDir,
    127                                             StringRef IndexName);
    128 
    129   /// \brief This function merges a definition from a separate AST Unit into
    130   ///        the current one which was created by the compiler instance that
    131   ///        was passed to the constructor.
    132   ///
    133   /// \return Returns the resulting definition or an error.
    134   llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD);
    135 
    136   /// \brief Get a name to identify a function.
    137   static std::string getLookupName(const NamedDecl *ND);
    138 
    139   /// \brief Emit diagnostics for the user for potential configuration errors.
    140   void emitCrossTUDiagnostics(const IndexError &IE);
    141 
    142 private:
    143   ASTImporter &getOrCreateASTImporter(ASTContext &From);
    144   const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC,
    145                                                 StringRef LookupFnName);
    146 
    147   llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap;
    148   llvm::StringMap<clang::ASTUnit *> FunctionASTUnitMap;
    149   llvm::StringMap<std::string> FunctionFileMap;
    150   llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>>
    151       ASTUnitImporterMap;
    152   CompilerInstance &CI;
    153   ASTContext &Context;
    154 };
    155 
    156 } // namespace cross_tu
    157 } // namespace clang
    158 
    159 #endif // LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
    160