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