Home | History | Annotate | Line # | Download | only in Frontend
      1 //===- Utils.h - Misc utilities for the front-end ---------------*- 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 header contains miscellaneous utilities for various front-end actions.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_CLANG_FRONTEND_UTILS_H
     14 #define LLVM_CLANG_FRONTEND_UTILS_H
     15 
     16 #include "clang/Basic/Diagnostic.h"
     17 #include "clang/Basic/LLVM.h"
     18 #include "clang/Driver/OptionUtils.h"
     19 #include "clang/Frontend/DependencyOutputOptions.h"
     20 #include "llvm/ADT/ArrayRef.h"
     21 #include "llvm/ADT/IntrusiveRefCntPtr.h"
     22 #include "llvm/ADT/StringMap.h"
     23 #include "llvm/ADT/StringRef.h"
     24 #include "llvm/ADT/StringSet.h"
     25 #include "llvm/Option/OptSpecifier.h"
     26 #include "llvm/Support/FileCollector.h"
     27 #include "llvm/Support/VirtualFileSystem.h"
     28 #include <cstdint>
     29 #include <memory>
     30 #include <string>
     31 #include <system_error>
     32 #include <utility>
     33 #include <vector>
     34 
     35 namespace llvm {
     36 
     37 class Triple;
     38 
     39 } // namespace llvm
     40 
     41 namespace clang {
     42 
     43 class ASTReader;
     44 class CompilerInstance;
     45 class CompilerInvocation;
     46 class DiagnosticsEngine;
     47 class ExternalSemaSource;
     48 class FrontendOptions;
     49 class HeaderSearch;
     50 class HeaderSearchOptions;
     51 class LangOptions;
     52 class PCHContainerReader;
     53 class Preprocessor;
     54 class PreprocessorOptions;
     55 class PreprocessorOutputOptions;
     56 
     57 /// Apply the header search options to get given HeaderSearch object.
     58 void ApplyHeaderSearchOptions(HeaderSearch &HS,
     59                               const HeaderSearchOptions &HSOpts,
     60                               const LangOptions &Lang,
     61                               const llvm::Triple &triple);
     62 
     63 /// InitializePreprocessor - Initialize the preprocessor getting it and the
     64 /// environment ready to process a single file.
     65 void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts,
     66                             const PCHContainerReader &PCHContainerRdr,
     67                             const FrontendOptions &FEOpts);
     68 
     69 /// DoPrintPreprocessedInput - Implement -E mode.
     70 void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
     71                               const PreprocessorOutputOptions &Opts);
     72 
     73 /// An interface for collecting the dependencies of a compilation. Users should
     74 /// use \c attachToPreprocessor and \c attachToASTReader to get all of the
     75 /// dependencies.
     76 /// FIXME: Migrate DependencyGraphGen to use this interface.
     77 class DependencyCollector {
     78 public:
     79   virtual ~DependencyCollector();
     80 
     81   virtual void attachToPreprocessor(Preprocessor &PP);
     82   virtual void attachToASTReader(ASTReader &R);
     83   ArrayRef<std::string> getDependencies() const { return Dependencies; }
     84 
     85   /// Called when a new file is seen. Return true if \p Filename should be added
     86   /// to the list of dependencies.
     87   ///
     88   /// The default implementation ignores <built-in> and system files.
     89   virtual bool sawDependency(StringRef Filename, bool FromModule,
     90                              bool IsSystem, bool IsModuleFile, bool IsMissing);
     91 
     92   /// Called when the end of the main file is reached.
     93   virtual void finishedMainFile(DiagnosticsEngine &Diags) {}
     94 
     95   /// Return true if system files should be passed to sawDependency().
     96   virtual bool needSystemDependencies() { return false; }
     97 
     98   /// Add a dependency \p Filename if it has not been seen before and
     99   /// sawDependency() returns true.
    100   virtual void maybeAddDependency(StringRef Filename, bool FromModule,
    101                                   bool IsSystem, bool IsModuleFile,
    102                                   bool IsMissing);
    103 
    104 protected:
    105   /// Return true if the filename was added to the list of dependencies, false
    106   /// otherwise.
    107   bool addDependency(StringRef Filename);
    108 
    109 private:
    110   llvm::StringSet<> Seen;
    111   std::vector<std::string> Dependencies;
    112 };
    113 
    114 /// Builds a dependency file when attached to a Preprocessor (for includes) and
    115 /// ASTReader (for module imports), and writes it out at the end of processing
    116 /// a source file.  Users should attach to the ast reader whenever a module is
    117 /// loaded.
    118 class DependencyFileGenerator : public DependencyCollector {
    119 public:
    120   DependencyFileGenerator(const DependencyOutputOptions &Opts);
    121 
    122   void attachToPreprocessor(Preprocessor &PP) override;
    123 
    124   void finishedMainFile(DiagnosticsEngine &Diags) override;
    125 
    126   bool needSystemDependencies() final override { return IncludeSystemHeaders; }
    127 
    128   bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem,
    129                      bool IsModuleFile, bool IsMissing) final override;
    130 
    131 protected:
    132   void outputDependencyFile(llvm::raw_ostream &OS);
    133 
    134 private:
    135   void outputDependencyFile(DiagnosticsEngine &Diags);
    136 
    137   std::string OutputFile;
    138   std::vector<std::string> Targets;
    139   bool IncludeSystemHeaders;
    140   bool PhonyTarget;
    141   bool AddMissingHeaderDeps;
    142   bool SeenMissingHeader;
    143   bool IncludeModuleFiles;
    144   DependencyOutputFormat OutputFormat;
    145   unsigned InputFileIndex;
    146 };
    147 
    148 /// Collects the dependencies for imported modules into a directory.  Users
    149 /// should attach to the AST reader whenever a module is loaded.
    150 class ModuleDependencyCollector : public DependencyCollector {
    151   std::string DestDir;
    152   bool HasErrors = false;
    153   llvm::StringSet<> Seen;
    154   llvm::vfs::YAMLVFSWriter VFSWriter;
    155   llvm::FileCollector::PathCanonicalizer Canonicalizer;
    156 
    157   std::error_code copyToRoot(StringRef Src, StringRef Dst = {});
    158 
    159 public:
    160   ModuleDependencyCollector(std::string DestDir)
    161       : DestDir(std::move(DestDir)) {}
    162   ~ModuleDependencyCollector() override { writeFileMap(); }
    163 
    164   StringRef getDest() { return DestDir; }
    165   virtual bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; }
    166   virtual void addFile(StringRef Filename, StringRef FileDst = {});
    167 
    168   virtual void addFileMapping(StringRef VPath, StringRef RPath) {
    169     VFSWriter.addFileMapping(VPath, RPath);
    170   }
    171 
    172   void attachToPreprocessor(Preprocessor &PP) override;
    173   void attachToASTReader(ASTReader &R) override;
    174 
    175   virtual void writeFileMap();
    176   virtual bool hasErrors() { return HasErrors; }
    177 };
    178 
    179 /// AttachDependencyGraphGen - Create a dependency graph generator, and attach
    180 /// it to the given preprocessor.
    181 void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
    182                               StringRef SysRoot);
    183 
    184 /// AttachHeaderIncludeGen - Create a header include list generator, and attach
    185 /// it to the given preprocessor.
    186 ///
    187 /// \param DepOpts - Options controlling the output.
    188 /// \param ShowAllHeaders - If true, show all header information instead of just
    189 /// headers following the predefines buffer. This is useful for making sure
    190 /// includes mentioned on the command line are also reported, but differs from
    191 /// the default behavior used by -H.
    192 /// \param OutputPath - If non-empty, a path to write the header include
    193 /// information to, instead of writing to stderr.
    194 /// \param ShowDepth - Whether to indent to show the nesting of the includes.
    195 /// \param MSStyle - Whether to print in cl.exe /showIncludes style.
    196 void AttachHeaderIncludeGen(Preprocessor &PP,
    197                             const DependencyOutputOptions &DepOpts,
    198                             bool ShowAllHeaders = false,
    199                             StringRef OutputPath = {},
    200                             bool ShowDepth = true, bool MSStyle = false);
    201 
    202 /// The ChainedIncludesSource class converts headers to chained PCHs in
    203 /// memory, mainly for testing.
    204 IntrusiveRefCntPtr<ExternalSemaSource>
    205 createChainedIncludesSource(CompilerInstance &CI,
    206                             IntrusiveRefCntPtr<ExternalSemaSource> &Reader);
    207 
    208 /// createInvocationFromCommandLine - Construct a compiler invocation object for
    209 /// a command line argument vector.
    210 ///
    211 /// \param ShouldRecoverOnErrors - whether we should attempt to return a
    212 /// non-null (and possibly incorrect) CompilerInvocation if any errors were
    213 /// encountered. When this flag is false, always return null on errors.
    214 ///
    215 /// \param CC1Args - if non-null, will be populated with the args to cc1
    216 /// expanded from \p Args. May be set even if nullptr is returned.
    217 ///
    218 /// \return A CompilerInvocation, or nullptr if none was built for the given
    219 /// argument vector.
    220 std::unique_ptr<CompilerInvocation> createInvocationFromCommandLine(
    221     ArrayRef<const char *> Args,
    222     IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
    223         IntrusiveRefCntPtr<DiagnosticsEngine>(),
    224     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr,
    225     bool ShouldRecoverOnErrors = false,
    226     std::vector<std::string> *CC1Args = nullptr);
    227 
    228 // Frontend timing utils
    229 
    230 } // namespace clang
    231 
    232 #endif // LLVM_CLANG_FRONTEND_UTILS_H
    233