1327952Sdim//===- HeaderSearch.h - Resolve Header File Locations -----------*- C++ -*-===//
2193326Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193326Sed//
7193326Sed//===----------------------------------------------------------------------===//
8193326Sed//
9193326Sed// This file defines the HeaderSearch interface.
10193326Sed//
11193326Sed//===----------------------------------------------------------------------===//
12193326Sed
13193326Sed#ifndef LLVM_CLANG_LEX_HEADERSEARCH_H
14193326Sed#define LLVM_CLANG_LEX_HEADERSEARCH_H
15193326Sed
16327952Sdim#include "clang/Basic/SourceLocation.h"
17327952Sdim#include "clang/Basic/SourceManager.h"
18193326Sed#include "clang/Lex/DirectoryLookup.h"
19344779Sdim#include "clang/Lex/HeaderMap.h"
20234353Sdim#include "clang/Lex/ModuleMap.h"
21239462Sdim#include "llvm/ADT/ArrayRef.h"
22327952Sdim#include "llvm/ADT/DenseMap.h"
23193326Sed#include "llvm/ADT/StringMap.h"
24226633Sdim#include "llvm/ADT/StringSet.h"
25327952Sdim#include "llvm/ADT/StringRef.h"
26226633Sdim#include "llvm/Support/Allocator.h"
27327952Sdim#include <cassert>
28327952Sdim#include <cstddef>
29276479Sdim#include <memory>
30327952Sdim#include <string>
31327952Sdim#include <utility>
32193326Sed#include <vector>
33193326Sed
34193326Sednamespace clang {
35327952Sdim
36327952Sdimclass DiagnosticsEngine;
37327952Sdimclass DirectoryEntry;
38288943Sdimclass ExternalPreprocessorSource;
39193326Sedclass FileEntry;
40193326Sedclass FileManager;
41243830Sdimclass HeaderSearchOptions;
42193326Sedclass IdentifierInfo;
43327952Sdimclass LangOptions;
44327952Sdimclass Module;
45288943Sdimclass Preprocessor;
46327952Sdimclass TargetInfo;
47193326Sed
48341825Sdim/// The preprocessor keeps track of this information for each
49239462Sdim/// file that is \#included.
50193326Sedstruct HeaderFileInfo {
51341825Sdim  /// True if this is a \#import'd or \#pragma once file.
52218893Sdim  unsigned isImport : 1;
53198092Srdivacky
54341825Sdim  /// True if this is a \#pragma once file.
55223017Sdim  unsigned isPragmaOnce : 1;
56223017Sdim
57344779Sdim  /// Keep track of whether this is a system header, and if so,
58193326Sed  /// whether it is C++ clean or not.  This can be set by the include paths or
59239462Sdim  /// by \#pragma gcc system_header.  This is an instance of
60193326Sed  /// SrcMgr::CharacteristicKind.
61321369Sdim  unsigned DirInfo : 3;
62198092Srdivacky
63341825Sdim  /// Whether this header file info was supplied by an external source,
64296417Sdim  /// and has not changed since.
65218893Sdim  unsigned External : 1;
66249423Sdim
67341825Sdim  /// Whether this header is part of a module.
68249423Sdim  unsigned isModuleHeader : 1;
69261991Sdim
70341825Sdim  /// Whether this header is part of the module that we are building.
71261991Sdim  unsigned isCompilingModuleHeader : 1;
72261991Sdim
73341825Sdim  /// Whether this structure is considered to already have been
74218893Sdim  /// "resolved", meaning that it was loaded from the external source.
75218893Sdim  unsigned Resolved : 1;
76341825Sdim
77341825Sdim  /// Whether this is a header inside a framework that is currently
78341825Sdim  /// being built.
79226633Sdim  ///
80226633Sdim  /// When a framework is being built, the headers have not yet been placed
81226633Sdim  /// into the appropriate framework subdirectories, and therefore are
82226633Sdim  /// provided via a header map. This bit indicates when this is one of
83226633Sdim  /// those framework headers.
84226633Sdim  unsigned IndexHeaderMapHeader : 1;
85276479Sdim
86341825Sdim  /// Whether this file has been looked up as a header.
87276479Sdim  unsigned IsValid : 1;
88341825Sdim
89341825Sdim  /// The number of times the file has been included already.
90327952Sdim  unsigned short NumIncludes = 0;
91198092Srdivacky
92341825Sdim  /// The ID number of the controlling macro.
93218893Sdim  ///
94218893Sdim  /// This ID number will be non-zero when there is a controlling
95218893Sdim  /// macro whose IdentifierInfo may not yet have been loaded from
96218893Sdim  /// external storage.
97327952Sdim  unsigned ControllingMacroID = 0;
98218893Sdim
99239462Sdim  /// If this file has a \#ifndef XXX (or equivalent) guard that
100239462Sdim  /// protects the entire contents of the file, this is the identifier
101193326Sed  /// for the macro that controls whether or not it has any effect.
102193326Sed  ///
103193326Sed  /// Note: Most clients should use getControllingMacro() to access
104193326Sed  /// the controlling macro of this header, since
105193326Sed  /// getControllingMacro() is able to load a controlling macro from
106193326Sed  /// external storage.
107327952Sdim  const IdentifierInfo *ControllingMacro = nullptr;
108193326Sed
109341825Sdim  /// If this header came from a framework include, this is the name
110226633Sdim  /// of the framework.
111226633Sdim  StringRef Framework;
112341825Sdim
113198092Srdivacky  HeaderFileInfo()
114341825Sdim      : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
115327952Sdim        External(false), isModuleHeader(false), isCompilingModuleHeader(false),
116327952Sdim        Resolved(false), IndexHeaderMapHeader(false), IsValid(false)  {}
117193326Sed
118341825Sdim  /// Retrieve the controlling macro for this header file, if
119193326Sed  /// any.
120288943Sdim  const IdentifierInfo *
121288943Sdim  getControllingMacro(ExternalPreprocessorSource *External);
122288943Sdim
123341825Sdim  /// Determine whether this is a non-default header file info, e.g.,
124218893Sdim  /// it corresponds to an actual header we've included or tried to include.
125218893Sdim  bool isNonDefault() const {
126341825Sdim    return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
127223017Sdim      ControllingMacroID;
128218893Sdim  }
129193326Sed};
130193326Sed
131341825Sdim/// An external source of header file information, which may supply
132218893Sdim/// information about header files already included.
133218893Sdimclass ExternalHeaderFileInfoSource {
134218893Sdimpublic:
135218893Sdim  virtual ~ExternalHeaderFileInfoSource();
136341825Sdim
137341825Sdim  /// Retrieve the header file information for the given file entry.
138218893Sdim  ///
139218893Sdim  /// \returns Header file information for the given file entry, with the
140341825Sdim  /// \c External bit set. If the file entry is not known, return a
141218893Sdim  /// default-constructed \c HeaderFileInfo.
142218893Sdim  virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
143218893Sdim};
144341825Sdim
145353358Sdim/// This structure is used to record entries in our framework cache.
146353358Sdimstruct FrameworkCacheEntry {
147353358Sdim  /// The directory entry which should be used for the cached framework.
148353358Sdim  const DirectoryEntry *Directory;
149353358Sdim
150353358Sdim  /// Whether this framework has been "user-specified" to be treated as if it
151353358Sdim  /// were a system framework (even if it was found outside a system framework
152353358Sdim  /// directory).
153353358Sdim  bool IsUserSpecifiedSystemFramework;
154353358Sdim};
155353358Sdim
156341825Sdim/// Encapsulates the information needed to find the file referenced
157239462Sdim/// by a \#include or \#include_next, (sub-)framework lookup, etc.
158193326Sedclass HeaderSearch {
159327952Sdim  friend class DirectoryLookup;
160327952Sdim
161341825Sdim  /// Header-search options used to initialize this header search.
162314564Sdim  std::shared_ptr<HeaderSearchOptions> HSOpts;
163243830Sdim
164276479Sdim  DiagnosticsEngine &Diags;
165193326Sed  FileManager &FileMgr;
166327952Sdim
167239462Sdim  /// \#include search path information.  Requests for \#include "x" search the
168239462Sdim  /// directory of the \#including file first, then each directory in SearchDirs
169223017Sdim  /// consecutively. Requests for <x> search the current dir first, then each
170223017Sdim  /// directory in SearchDirs, starting at AngledDirIdx, consecutively.  If
171193326Sed  /// NoCurDirSearch is true, then the check for the file in the current
172221345Sdim  /// directory is suppressed.
173193326Sed  std::vector<DirectoryLookup> SearchDirs;
174327952Sdim  unsigned AngledDirIdx = 0;
175327952Sdim  unsigned SystemDirIdx = 0;
176327952Sdim  bool NoCurDirSearch = false;
177198092Srdivacky
178341825Sdim  /// \#include prefixes for which the 'system header' property is
179239462Sdim  /// overridden.
180239462Sdim  ///
181239462Sdim  /// For a \#include "x" or \#include \<x> directive, the last string in this
182239462Sdim  /// list which is a prefix of 'x' determines whether the file is treated as
183239462Sdim  /// a system header.
184327952Sdim  std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes;
185239462Sdim
186341825Sdim  /// The path to the module cache.
187226633Sdim  std::string ModuleCachePath;
188341825Sdim
189341825Sdim  /// All of the preprocessor-specific data about files that are
190239462Sdim  /// included, indexed by the FileEntry's UID.
191296417Sdim  mutable std::vector<HeaderFileInfo> FileInfo;
192193326Sed
193276479Sdim  /// Keeps track of each lookup performed by LookupFile.
194276479Sdim  struct LookupFileCacheInfo {
195276479Sdim    /// Starting index in SearchDirs that the cached search was performed from.
196276479Sdim    /// If there is a hit and this value doesn't match the current query, the
197276479Sdim    /// cache has to be ignored.
198327952Sdim    unsigned StartIdx = 0;
199327952Sdim
200276479Sdim    /// The entry in SearchDirs that satisfied the query.
201327952Sdim    unsigned HitIdx = 0;
202327952Sdim
203276479Sdim    /// This is non-null if the original filename was mapped to a framework
204276479Sdim    /// include via a headermap.
205327952Sdim    const char *MappedName = nullptr;
206198092Srdivacky
207276479Sdim    /// Default constructor -- Initialize all members with zero.
208327952Sdim    LookupFileCacheInfo() = default;
209276479Sdim
210276479Sdim    void reset(unsigned StartIdx) {
211276479Sdim      this->StartIdx = StartIdx;
212276479Sdim      this->MappedName = nullptr;
213276479Sdim    }
214276479Sdim  };
215276479Sdim  llvm::StringMap<LookupFileCacheInfo, llvm::BumpPtrAllocator> LookupFileCache;
216276479Sdim
217341825Sdim  /// Collection mapping a framework or subframework
218193326Sed  /// name like "Carbon" to the Carbon.framework directory.
219234353Sdim  llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap;
220193326Sed
221344779Sdim  /// Maps include file names (including the quotes or
222234353Sdim  /// angle brackets) to other include file names.  This is used to support the
223234353Sdim  /// include_alias pragma for Microsoft compatibility.
224327952Sdim  using IncludeAliasMap =
225327952Sdim      llvm::StringMap<std::string, llvm::BumpPtrAllocator>;
226276479Sdim  std::unique_ptr<IncludeAliasMap> IncludeAliases;
227234353Sdim
228344779Sdim  /// This is a mapping from FileEntry -> HeaderMap, uniquing headermaps.
229344779Sdim  std::vector<std::pair<const FileEntry *, std::unique_ptr<HeaderMap>>> HeaderMaps;
230193326Sed
231341825Sdim  /// The mapping between modules and headers.
232249423Sdim  mutable ModuleMap ModMap;
233341825Sdim
234341825Sdim  /// Describes whether a given directory has a module map in it.
235234353Sdim  llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap;
236280031Sdim
237341825Sdim  /// Set of module map files we've already loaded, and a flag indicating
238280031Sdim  /// whether they were valid or not.
239280031Sdim  llvm::DenseMap<const FileEntry *, bool> LoadedModuleMaps;
240280031Sdim
241341825Sdim  /// Uniqued set of framework names, which is used to track which
242226633Sdim  /// headers were included as framework headers.
243226633Sdim  llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames;
244341825Sdim
245341825Sdim  /// Entity used to resolve the identifier IDs of controlling
246288943Sdim  /// macros into IdentifierInfo pointers, and keep the identifire up to date,
247288943Sdim  /// as needed.
248327952Sdim  ExternalPreprocessorSource *ExternalLookup = nullptr;
249193326Sed
250341825Sdim  /// Entity used to look up stored header file information.
251327952Sdim  ExternalHeaderFileInfoSource *ExternalSource = nullptr;
252341825Sdim
253193326Sedpublic:
254314564Sdim  HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
255261991Sdim               SourceManager &SourceMgr, DiagnosticsEngine &Diags,
256234353Sdim               const LangOptions &LangOpts, const TargetInfo *Target);
257327952Sdim  HeaderSearch(const HeaderSearch &) = delete;
258327952Sdim  HeaderSearch &operator=(const HeaderSearch &) = delete;
259193326Sed
260341825Sdim  /// Retrieve the header-search options with which this header search
261243830Sdim  /// was initialized.
262243830Sdim  HeaderSearchOptions &getHeaderSearchOpts() const { return *HSOpts; }
263341825Sdim
264193326Sed  FileManager &getFileMgr() const { return FileMgr; }
265193326Sed
266341825Sdim  DiagnosticsEngine &getDiags() const { return Diags; }
267341825Sdim
268341825Sdim  /// Interface for setting the file search paths.
269193326Sed  void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
270223017Sdim                      unsigned angledDirIdx, unsigned systemDirIdx,
271223017Sdim                      bool noCurDirSearch) {
272223017Sdim    assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
273341825Sdim        "Directory indices are unordered");
274193326Sed    SearchDirs = dirs;
275223017Sdim    AngledDirIdx = angledDirIdx;
276193326Sed    SystemDirIdx = systemDirIdx;
277193326Sed    NoCurDirSearch = noCurDirSearch;
278193326Sed    //LookupFileCache.clear();
279193326Sed  }
280198092Srdivacky
281341825Sdim  /// Add an additional search path.
282234353Sdim  void AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
283234353Sdim    unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
284234353Sdim    SearchDirs.insert(SearchDirs.begin() + idx, dir);
285234353Sdim    if (!isAngled)
286234353Sdim      AngledDirIdx++;
287234353Sdim    SystemDirIdx++;
288234353Sdim  }
289234353Sdim
290341825Sdim  /// Set the list of system header prefixes.
291327952Sdim  void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) {
292239462Sdim    SystemHeaderPrefixes.assign(P.begin(), P.end());
293239462Sdim  }
294239462Sdim
295341825Sdim  /// Checks whether the map exists or not.
296276479Sdim  bool HasIncludeAliasMap() const { return (bool)IncludeAliases; }
297234353Sdim
298341825Sdim  /// Map the source include name to the dest include name.
299239462Sdim  ///
300341825Sdim  /// The Source should include the angle brackets or quotes, the dest
301234353Sdim  /// should not.  This allows for distinction between <> and "" headers.
302234353Sdim  void AddIncludeAlias(StringRef Source, StringRef Dest) {
303234353Sdim    if (!IncludeAliases)
304234353Sdim      IncludeAliases.reset(new IncludeAliasMap);
305234353Sdim    (*IncludeAliases)[Source] = Dest;
306234353Sdim  }
307234353Sdim
308344779Sdim  /// Maps one header file name to a different header
309234353Sdim  /// file name, for use with the include_alias pragma.  Note that the source
310234353Sdim  /// file name should include the angle brackets or quotes.  Returns StringRef
311234353Sdim  /// as null if the header cannot be mapped.
312234353Sdim  StringRef MapHeaderToIncludeAlias(StringRef Source) {
313234353Sdim    assert(IncludeAliases && "Trying to map headers when there's no map");
314234353Sdim
315234353Sdim    // Do any filename replacements before anything else
316234353Sdim    IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source);
317234353Sdim    if (Iter != IncludeAliases->end())
318234353Sdim      return Iter->second;
319327952Sdim    return {};
320234353Sdim  }
321234353Sdim
322341825Sdim  /// Set the path to the module cache.
323234353Sdim  void setModuleCachePath(StringRef CachePath) {
324226633Sdim    ModuleCachePath = CachePath;
325226633Sdim  }
326341825Sdim
327341825Sdim  /// Retrieve the path to the module cache.
328234353Sdim  StringRef getModuleCachePath() const { return ModuleCachePath; }
329243830Sdim
330341825Sdim  /// Consider modules when including files from this directory.
331243830Sdim  void setDirectoryHasModuleMap(const DirectoryEntry* Dir) {
332243830Sdim    DirectoryHasModuleMap[Dir] = true;
333243830Sdim  }
334341825Sdim
335341825Sdim  /// Forget everything we know about headers so far.
336193326Sed  void ClearFileInfo() {
337193326Sed    FileInfo.clear();
338193326Sed  }
339198092Srdivacky
340288943Sdim  void SetExternalLookup(ExternalPreprocessorSource *EPS) {
341288943Sdim    ExternalLookup = EPS;
342193326Sed  }
343193326Sed
344288943Sdim  ExternalPreprocessorSource *getExternalLookup() const {
345218893Sdim    return ExternalLookup;
346218893Sdim  }
347341825Sdim
348341825Sdim  /// Set the external source of header information.
349218893Sdim  void SetExternalSource(ExternalHeaderFileInfoSource *ES) {
350218893Sdim    ExternalSource = ES;
351218893Sdim  }
352341825Sdim
353341825Sdim  /// Set the target information for the header search, if not
354234353Sdim  /// already known.
355234353Sdim  void setTarget(const TargetInfo &Target);
356341825Sdim
357341825Sdim  /// Given a "foo" or \<foo> reference, look up the indicated file,
358221345Sdim  /// return null on failure.
359221345Sdim  ///
360221345Sdim  /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member
361221345Sdim  /// the file was found in, or null if not applicable.
362221345Sdim  ///
363276479Sdim  /// \param IncludeLoc Used for diagnostics if valid.
364276479Sdim  ///
365221345Sdim  /// \param isAngled indicates whether the file reference is a <> reference.
366221345Sdim  ///
367221345Sdim  /// \param CurDir If non-null, the file was found in the specified directory
368239462Sdim  /// search location.  This is used to implement \#include_next.
369221345Sdim  ///
370276479Sdim  /// \param Includers Indicates where the \#including file(s) are, in case
371276479Sdim  /// relative searches are needed. In reverse order of inclusion.
372221345Sdim  ///
373221345Sdim  /// \param SearchPath If non-null, will be set to the search path relative
374221345Sdim  /// to which the file was found. If the include path is absolute, SearchPath
375221345Sdim  /// will be set to an empty string.
376221345Sdim  ///
377221345Sdim  /// \param RelativePath If non-null, will be set to the path relative to
378221345Sdim  /// SearchPath at which the file was found. This only differs from the
379221345Sdim  /// Filename for framework includes.
380226633Sdim  ///
381226633Sdim  /// \param SuggestedModule If non-null, and the file found is semantically
382234353Sdim  /// part of a known module, this will be set to the module that should
383234353Sdim  /// be imported instead of preprocessing/parsing the file found.
384321369Sdim  ///
385321369Sdim  /// \param IsMapped If non-null, and the search involved header maps, set to
386321369Sdim  /// true.
387353358Sdim  ///
388353358Sdim  /// \param IsFrameworkFound If non-null, will be set to true if a framework is
389353358Sdim  /// found in any of searched SearchDirs. Will be set to false if a framework
390353358Sdim  /// is found only through header maps. Doesn't guarantee the requested file is
391353358Sdim  /// found.
392360784Sdim  Optional<FileEntryRef> LookupFile(
393280031Sdim      StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
394280031Sdim      const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
395280031Sdim      ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
396280031Sdim      SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
397296417Sdim      Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
398353358Sdim      bool *IsMapped, bool *IsFrameworkFound, bool SkipCache = false,
399353358Sdim      bool BuildSystemModule = false);
400198092Srdivacky
401341825Sdim  /// Look up a subframework for the specified \#include file.
402239462Sdim  ///
403239462Sdim  /// For example, if \#include'ing <HIToolbox/HIToolbox.h> from
404239462Sdim  /// within ".../Carbon.framework/Headers/Carbon.h", check to see if
405239462Sdim  /// HIToolbox is a subframework within Carbon.framework.  If so, return
406239462Sdim  /// the FileEntry for the designated file, otherwise return null.
407360784Sdim  Optional<FileEntryRef> LookupSubframeworkHeader(
408344779Sdim      StringRef Filename, const FileEntry *ContextFileEnt,
409296417Sdim      SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
410296417Sdim      Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
411198092Srdivacky
412341825Sdim  /// Look up the specified framework name in our framework cache.
413239462Sdim  /// \returns The DirectoryEntry it is in if we know, null otherwise.
414234353Sdim  FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) {
415280031Sdim    return FrameworkMap[FWName];
416193326Sed  }
417198092Srdivacky
418341825Sdim  /// Mark the specified file as a target of a \#include,
419239462Sdim  /// \#include_next, or \#import directive.
420239462Sdim  ///
421239462Sdim  /// \return false if \#including the file will have no effect or true
422239462Sdim  /// if we should include it.
423288943Sdim  bool ShouldEnterIncludeFile(Preprocessor &PP, const FileEntry *File,
424314564Sdim                              bool isImport, bool ModulesEnabled,
425344779Sdim                              Module *M);
426198092Srdivacky
427341825Sdim  /// Return whether the specified file is a normal header,
428193326Sed  /// a system header, or a C++ friendly system header.
429193326Sed  SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) {
430193326Sed    return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
431193326Sed  }
432198092Srdivacky
433341825Sdim  /// Mark the specified file as a "once only" file, e.g. due to
434239462Sdim  /// \#pragma once.
435193326Sed  void MarkFileIncludeOnce(const FileEntry *File) {
436223017Sdim    HeaderFileInfo &FI = getFileInfo(File);
437223017Sdim    FI.isImport = true;
438223017Sdim    FI.isPragmaOnce = true;
439193326Sed  }
440193326Sed
441341825Sdim  /// Mark the specified file as a system header, e.g. due to
442239462Sdim  /// \#pragma GCC system_header.
443193326Sed  void MarkFileSystemHeader(const FileEntry *File) {
444193326Sed    getFileInfo(File).DirInfo = SrcMgr::C_System;
445193326Sed  }
446198092Srdivacky
447341825Sdim  /// Mark the specified file as part of a module.
448344779Sdim  void MarkFileModuleHeader(const FileEntry *FE,
449261991Sdim                            ModuleMap::ModuleHeaderRole Role,
450344779Sdim                            bool isCompilingModuleHeader);
451249423Sdim
452341825Sdim  /// Increment the count for the number of times the specified
453239462Sdim  /// FileEntry has been entered.
454193326Sed  void IncrementIncludeCount(const FileEntry *File) {
455193326Sed    ++getFileInfo(File).NumIncludes;
456193326Sed  }
457198092Srdivacky
458341825Sdim  /// Mark the specified file as having a controlling macro.
459239462Sdim  ///
460239462Sdim  /// This is used by the multiple-include optimization to eliminate
461239462Sdim  /// no-op \#includes.
462193326Sed  void SetFileControllingMacro(const FileEntry *File,
463193326Sed                               const IdentifierInfo *ControllingMacro) {
464193326Sed    getFileInfo(File).ControllingMacro = ControllingMacro;
465193326Sed  }
466198092Srdivacky
467341825Sdim  /// Return true if this is the first time encountering this header.
468261991Sdim  bool FirstTimeLexingFile(const FileEntry *File) {
469261991Sdim    return getFileInfo(File).NumIncludes == 1;
470261991Sdim  }
471261991Sdim
472341825Sdim  /// Determine whether this file is intended to be safe from
473239462Sdim  /// multiple inclusions, e.g., it has \#pragma once or a controlling
474223017Sdim  /// macro.
475223017Sdim  ///
476239462Sdim  /// This routine does not consider the effect of \#import
477223017Sdim  bool isFileMultipleIncludeGuarded(const FileEntry *File);
478223017Sdim
479344779Sdim  /// This method returns a HeaderMap for the specified
480239462Sdim  /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
481193326Sed  const HeaderMap *CreateHeaderMap(const FileEntry *FE);
482198092Srdivacky
483341825Sdim  /// Get filenames for all registered header maps.
484314564Sdim  void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const;
485314564Sdim
486341825Sdim  /// Retrieve the name of the cached module file that should be used
487327952Sdim  /// to load the given module.
488226633Sdim  ///
489234353Sdim  /// \param Module The module whose module file name will be returned.
490226633Sdim  ///
491234353Sdim  /// \returns The name of the module file that corresponds to this module,
492234353Sdim  /// or an empty string if this module does not correspond to any module file.
493327952Sdim  std::string getCachedModuleFileName(Module *Module);
494234353Sdim
495341825Sdim  /// Retrieve the name of the prebuilt module file that should be used
496327952Sdim  /// to load a module with the given name.
497226633Sdim  ///
498239462Sdim  /// \param ModuleName The module whose module file name will be returned.
499234353Sdim  ///
500327952Sdim  /// \param FileMapOnly If true, then only look in the explicit module name
501327952Sdim  //  to file name map and skip the directory search.
502327952Sdim  ///
503327952Sdim  /// \returns The name of the module file that corresponds to this module,
504327952Sdim  /// or an empty string if this module does not correspond to any module file.
505327952Sdim  std::string getPrebuiltModuleFileName(StringRef ModuleName,
506327952Sdim                                        bool FileMapOnly = false);
507327952Sdim
508341825Sdim  /// Retrieve the name of the (to-be-)cached module file that should
509327952Sdim  /// be used to load a module with the given name.
510327952Sdim  ///
511327952Sdim  /// \param ModuleName The module whose module file name will be returned.
512327952Sdim  ///
513276479Sdim  /// \param ModuleMapPath A path that when combined with \c ModuleName
514276479Sdim  /// uniquely identifies this module. See Module::ModuleMap.
515276479Sdim  ///
516234353Sdim  /// \returns The name of the module file that corresponds to this module,
517234353Sdim  /// or an empty string if this module does not correspond to any module file.
518327952Sdim  std::string getCachedModuleFileName(StringRef ModuleName,
519327952Sdim                                      StringRef ModuleMapPath);
520234353Sdim
521341825Sdim  /// Lookup a module Search for a module with the given name.
522234353Sdim  ///
523234353Sdim  /// \param ModuleName The name of the module we're looking for.
524234353Sdim  ///
525234353Sdim  /// \param AllowSearch Whether we are allowed to search in the various
526234353Sdim  /// search directories to produce a module definition. If not, this lookup
527234353Sdim  /// will only return an already-known module.
528234353Sdim  ///
529341825Sdim  /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps
530341825Sdim  /// in subdirectories.
531341825Sdim  ///
532234353Sdim  /// \returns The module with the given name.
533341825Sdim  Module *lookupModule(StringRef ModuleName, bool AllowSearch = true,
534341825Sdim                       bool AllowExtraModuleMapSearch = false);
535276479Sdim
536341825Sdim  /// Try to find a module map file in the given directory, returning
537276479Sdim  /// \c nullptr if none is found.
538276479Sdim  const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir,
539276479Sdim                                       bool IsFramework);
540341825Sdim
541341825Sdim  /// Determine whether there is a module map that may map the header
542234353Sdim  /// with the given file name to a (sub)module.
543276479Sdim  /// Always returns false if modules are disabled.
544234353Sdim  ///
545234353Sdim  /// \param Filename The name of the file.
546234353Sdim  ///
547234353Sdim  /// \param Root The "root" directory, at which we should stop looking for
548234353Sdim  /// module maps.
549261991Sdim  ///
550261991Sdim  /// \param IsSystem Whether the directories we're looking at are system
551261991Sdim  /// header directories.
552261991Sdim  bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root,
553261991Sdim                    bool IsSystem);
554341825Sdim
555341825Sdim  /// Retrieve the module that corresponds to the given file, if any.
556234353Sdim  ///
557234353Sdim  /// \param File The header that we wish to map to a module.
558314564Sdim  /// \param AllowTextual Whether we want to find textual headers too.
559314564Sdim  ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File,
560314564Sdim                                             bool AllowTextual = false) const;
561314564Sdim
562341825Sdim  /// Read the contents of the given module map file.
563234353Sdim  ///
564234353Sdim  /// \param File The module map file.
565261991Sdim  /// \param IsSystem Whether this file is in a system header directory.
566321369Sdim  /// \param ID If the module map file is already mapped (perhaps as part of
567321369Sdim  ///        processing a preprocessed module), the ID of the file.
568321369Sdim  /// \param Offset [inout] An offset within ID to start parsing. On exit,
569321369Sdim  ///        filled by the end of the parsed contents (either EOF or the
570321369Sdim  ///        location of an end-of-module-map pragma).
571321369Sdim  /// \param OriginalModuleMapFile The original path to the module map file,
572321369Sdim  ///        used to resolve paths within the module (this is required when
573321369Sdim  ///        building the module from preprocessed source).
574234353Sdim  /// \returns true if an error occurred, false otherwise.
575321369Sdim  bool loadModuleMapFile(const FileEntry *File, bool IsSystem,
576321369Sdim                         FileID ID = FileID(), unsigned *Offset = nullptr,
577321369Sdim                         StringRef OriginalModuleMapFile = StringRef());
578234353Sdim
579341825Sdim  /// Collect the set of all known, top-level modules.
580234353Sdim  ///
581234353Sdim  /// \param Modules Will be filled with the set of known, top-level modules.
582249423Sdim  void collectAllModules(SmallVectorImpl<Module *> &Modules);
583261991Sdim
584341825Sdim  /// Load all known, top-level system modules.
585261991Sdim  void loadTopLevelSystemModules();
586261991Sdim
587234353Sdimprivate:
588341825Sdim  /// Lookup a module with the given module name and search-name.
589314564Sdim  ///
590314564Sdim  /// \param ModuleName The name of the module we're looking for.
591314564Sdim  ///
592314564Sdim  /// \param SearchName The "search-name" to derive filesystem paths from
593314564Sdim  /// when looking for the module map; this is usually equal to ModuleName,
594314564Sdim  /// but for compatibility with some buggy frameworks, additional attempts
595314564Sdim  /// may be made to find the module under a related-but-different search-name.
596314564Sdim  ///
597341825Sdim  /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps
598341825Sdim  /// in subdirectories.
599341825Sdim  ///
600314564Sdim  /// \returns The module named ModuleName.
601341825Sdim  Module *lookupModule(StringRef ModuleName, StringRef SearchName,
602341825Sdim                       bool AllowExtraModuleMapSearch = false);
603314564Sdim
604341825Sdim  /// Retrieve a module with the given name, which may be part of the
605234353Sdim  /// given framework.
606234353Sdim  ///
607234353Sdim  /// \param Name The name of the module to retrieve.
608234353Sdim  ///
609234353Sdim  /// \param Dir The framework directory (e.g., ModuleName.framework).
610234353Sdim  ///
611234353Sdim  /// \param IsSystem Whether the framework directory is part of the system
612234353Sdim  /// frameworks.
613234353Sdim  ///
614234353Sdim  /// \returns The module, if found; otherwise, null.
615341825Sdim  Module *loadFrameworkModule(StringRef Name,
616234353Sdim                              const DirectoryEntry *Dir,
617234353Sdim                              bool IsSystem);
618249423Sdim
619341825Sdim  /// Load all of the module maps within the immediate subdirectories
620249423Sdim  /// of the given search directory.
621249423Sdim  void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
622249423Sdim
623341825Sdim  /// Find and suggest a usable module for the given file.
624296417Sdim  ///
625296417Sdim  /// \return \c true if the file can be used, \c false if we are not permitted to
626296417Sdim  ///         find this file due to requirements from \p RequestingModule.
627296417Sdim  bool findUsableModuleForHeader(const FileEntry *File,
628296417Sdim                                 const DirectoryEntry *Root,
629296417Sdim                                 Module *RequestingModule,
630296417Sdim                                 ModuleMap::KnownHeader *SuggestedModule,
631296417Sdim                                 bool IsSystemHeaderDir);
632276479Sdim
633341825Sdim  /// Find and suggest a usable module for the given file, which is part of
634296417Sdim  /// the specified framework.
635296417Sdim  ///
636296417Sdim  /// \return \c true if the file can be used, \c false if we are not permitted to
637296417Sdim  ///         find this file due to requirements from \p RequestingModule.
638296417Sdim  bool findUsableModuleForFrameworkHeader(
639344779Sdim      const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
640296417Sdim      ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework);
641296417Sdim
642341825Sdim  /// Look up the file with the specified name and determine its owning
643296417Sdim  /// module.
644360784Sdim  Optional<FileEntryRef>
645309124Sdim  getFileAndSuggestModule(StringRef FileName, SourceLocation IncludeLoc,
646309124Sdim                          const DirectoryEntry *Dir, bool IsSystemHeaderDir,
647309124Sdim                          Module *RequestingModule,
648296417Sdim                          ModuleMap::KnownHeader *SuggestedModule);
649296417Sdim
650234353Sdimpublic:
651341825Sdim  /// Retrieve the module map.
652234353Sdim  ModuleMap &getModuleMap() { return ModMap; }
653341825Sdim
654341825Sdim  /// Retrieve the module map.
655296417Sdim  const ModuleMap &getModuleMap() const { return ModMap; }
656341825Sdim
657205408Srdivacky  unsigned header_file_size() const { return FileInfo.size(); }
658193326Sed
659341825Sdim  /// Return the HeaderFileInfo structure for the specified FileEntry,
660296417Sdim  /// in preparation for updating it in some way.
661296417Sdim  HeaderFileInfo &getFileInfo(const FileEntry *FE);
662234353Sdim
663341825Sdim  /// Return the HeaderFileInfo structure for the specified FileEntry,
664296417Sdim  /// if it has ever been filled in.
665296417Sdim  /// \param WantExternal Whether the caller wants purely-external header file
666296417Sdim  ///        info (where \p External is true).
667296417Sdim  const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
668296417Sdim                                            bool WantExternal = true) const;
669296417Sdim
670221345Sdim  // Used by external tools
671327952Sdim  using search_dir_iterator = std::vector<DirectoryLookup>::const_iterator;
672327952Sdim
673221345Sdim  search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); }
674221345Sdim  search_dir_iterator search_dir_end() const { return SearchDirs.end(); }
675221345Sdim  unsigned search_dir_size() const { return SearchDirs.size(); }
676221345Sdim
677223017Sdim  search_dir_iterator quoted_dir_begin() const {
678223017Sdim    return SearchDirs.begin();
679223017Sdim  }
680327952Sdim
681223017Sdim  search_dir_iterator quoted_dir_end() const {
682223017Sdim    return SearchDirs.begin() + AngledDirIdx;
683223017Sdim  }
684223017Sdim
685223017Sdim  search_dir_iterator angled_dir_begin() const {
686223017Sdim    return SearchDirs.begin() + AngledDirIdx;
687223017Sdim  }
688327952Sdim
689223017Sdim  search_dir_iterator angled_dir_end() const {
690223017Sdim    return SearchDirs.begin() + SystemDirIdx;
691223017Sdim  }
692223017Sdim
693221345Sdim  search_dir_iterator system_dir_begin() const {
694221345Sdim    return SearchDirs.begin() + SystemDirIdx;
695221345Sdim  }
696327952Sdim
697221345Sdim  search_dir_iterator system_dir_end() const { return SearchDirs.end(); }
698221345Sdim
699341825Sdim  /// Retrieve a uniqued framework name.
700226633Sdim  StringRef getUniqueFrameworkName(StringRef Framework);
701341825Sdim
702353358Sdim  /// Suggest a path by which the specified file could be found, for use in
703353358Sdim  /// diagnostics to suggest a #include. Returned path will only contain forward
704353358Sdim  /// slashes as separators. MainFile is the absolute path of the file that we
705353358Sdim  /// are generating the diagnostics for. It will try to shorten the path using
706353358Sdim  /// MainFile location, if none of the include search directories were prefix
707353358Sdim  /// of File.
708309124Sdim  ///
709309124Sdim  /// \param IsSystem If non-null, filled in to indicate whether the suggested
710309124Sdim  ///        path is relative to a system header directory.
711309124Sdim  std::string suggestPathToFileForDiagnostics(const FileEntry *File,
712353358Sdim                                              llvm::StringRef MainFile,
713309124Sdim                                              bool *IsSystem = nullptr);
714309124Sdim
715353358Sdim  /// Suggest a path by which the specified file could be found, for use in
716353358Sdim  /// diagnostics to suggest a #include. Returned path will only contain forward
717353358Sdim  /// slashes as separators. MainFile is the absolute path of the file that we
718353358Sdim  /// are generating the diagnostics for. It will try to shorten the path using
719353358Sdim  /// MainFile location, if none of the include search directories were prefix
720353358Sdim  /// of File.
721341825Sdim  ///
722341825Sdim  /// \param WorkingDir If non-empty, this will be prepended to search directory
723341825Sdim  /// paths that are relative.
724341825Sdim  std::string suggestPathToFileForDiagnostics(llvm::StringRef File,
725341825Sdim                                              llvm::StringRef WorkingDir,
726353358Sdim                                              llvm::StringRef MainFile,
727341825Sdim                                              bool *IsSystem = nullptr);
728341825Sdim
729193326Sed  void PrintStats();
730341825Sdim
731226633Sdim  size_t getTotalMemory() const;
732226633Sdim
733193326Sedprivate:
734341825Sdim  /// Describes what happened when we tried to load a module map file.
735234353Sdim  enum LoadModuleMapResult {
736341825Sdim    /// The module map file had already been loaded.
737234353Sdim    LMM_AlreadyLoaded,
738327952Sdim
739341825Sdim    /// The module map file was loaded by this invocation.
740234353Sdim    LMM_NewlyLoaded,
741327952Sdim
742341825Sdim    /// There is was directory with the given name.
743234353Sdim    LMM_NoDirectory,
744327952Sdim
745341825Sdim    /// There was either no module map file or the module map file was
746234353Sdim    /// invalid.
747234353Sdim    LMM_InvalidModuleMap
748234353Sdim  };
749276479Sdim
750276479Sdim  LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
751280031Sdim                                            bool IsSystem,
752321369Sdim                                            const DirectoryEntry *Dir,
753321369Sdim                                            FileID ID = FileID(),
754321369Sdim                                            unsigned *Offset = nullptr);
755276479Sdim
756341825Sdim  /// Try to load the module map file in the given directory.
757234353Sdim  ///
758234353Sdim  /// \param DirName The name of the directory where we will look for a module
759234353Sdim  /// map file.
760261991Sdim  /// \param IsSystem Whether this is a system header directory.
761276479Sdim  /// \param IsFramework Whether this is a framework directory.
762234353Sdim  ///
763234353Sdim  /// \returns The result of attempting to load the module map file from the
764234353Sdim  /// named directory.
765276479Sdim  LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem,
766276479Sdim                                        bool IsFramework);
767198092Srdivacky
768341825Sdim  /// Try to load the module map file in the given directory.
769234353Sdim  ///
770234353Sdim  /// \param Dir The directory where we will look for a module map file.
771261991Sdim  /// \param IsSystem Whether this is a system header directory.
772276479Sdim  /// \param IsFramework Whether this is a framework directory.
773234353Sdim  ///
774234353Sdim  /// \returns The result of attempting to load the module map file from the
775234353Sdim  /// named directory.
776261991Sdim  LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir,
777276479Sdim                                        bool IsSystem, bool IsFramework);
778193326Sed};
779193326Sed
780327952Sdim} // namespace clang
781193326Sed
782327952Sdim#endif // LLVM_CLANG_LEX_HEADERSEARCH_H
783