• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- HeaderSearch.h - Resolve Header File Locations ---------*- 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 defines the HeaderSearch interface.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_LEX_HEADERSEARCH_H
15 #define LLVM_CLANG_LEX_HEADERSEARCH_H
16 
17 #include "clang/Lex/DirectoryLookup.h"
18 #include "llvm/ADT/StringMap.h"
19 #include <vector>
20 
21 namespace clang {
22 
23 class ExternalIdentifierLookup;
24 class FileEntry;
25 class FileManager;
26 class IdentifierInfo;
27 
28 /// HeaderFileInfo - The preprocessor keeps track of this information for each
29 /// file that is #included.
30 struct HeaderFileInfo {
31   /// isImport - True if this is a #import'd or #pragma once file.
32   unsigned isImport : 1;
33 
34   /// isPragmaOnce - True if this is  #pragma once file.
35   unsigned isPragmaOnce : 1;
36 
37   /// DirInfo - Keep track of whether this is a system header, and if so,
38   /// whether it is C++ clean or not.  This can be set by the include paths or
39   /// by #pragma gcc system_header.  This is an instance of
40   /// SrcMgr::CharacteristicKind.
41   unsigned DirInfo : 2;
42 
43   /// \brief Whether this header file info was supplied by an external source.
44   unsigned External : 1;
45 
46   /// \brief Whether this structure is considered to already have been
47   /// "resolved", meaning that it was loaded from the external source.
48   unsigned Resolved : 1;
49 
50   /// NumIncludes - This is the number of times the file has been included
51   /// already.
52   unsigned short NumIncludes;
53 
54   /// \brief The ID number of the controlling macro.
55   ///
56   /// This ID number will be non-zero when there is a controlling
57   /// macro whose IdentifierInfo may not yet have been loaded from
58   /// external storage.
59   unsigned ControllingMacroID;
60 
61   /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
62   /// that protects the entire contents of the file, this is the identifier
63   /// for the macro that controls whether or not it has any effect.
64   ///
65   /// Note: Most clients should use getControllingMacro() to access
66   /// the controlling macro of this header, since
67   /// getControllingMacro() is able to load a controlling macro from
68   /// external storage.
69   const IdentifierInfo *ControllingMacro;
70 
HeaderFileInfoHeaderFileInfo71   HeaderFileInfo()
72     : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
73       External(false), Resolved(false), NumIncludes(0), ControllingMacroID(0),
74       ControllingMacro(0)  {}
75 
76   /// \brief Retrieve the controlling macro for this header file, if
77   /// any.
78   const IdentifierInfo *getControllingMacro(ExternalIdentifierLookup *External);
79 
80   /// \brief Determine whether this is a non-default header file info, e.g.,
81   /// it corresponds to an actual header we've included or tried to include.
isNonDefaultHeaderFileInfo82   bool isNonDefault() const {
83     return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
84       ControllingMacroID;
85   }
86 };
87 
88 /// \brief An external source of header file information, which may supply
89 /// information about header files already included.
90 class ExternalHeaderFileInfoSource {
91 public:
92   virtual ~ExternalHeaderFileInfoSource();
93 
94   /// \brief Retrieve the header file information for the given file entry.
95   ///
96   /// \returns Header file information for the given file entry, with the
97   /// \c External bit set. If the file entry is not known, return a
98   /// default-constructed \c HeaderFileInfo.
99   virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
100 };
101 
102 /// HeaderSearch - This class encapsulates the information needed to find the
103 /// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
104 class HeaderSearch {
105   FileManager &FileMgr;
106   /// #include search path information.  Requests for #include "x" search the
107   /// directory of the #including file first, then each directory in SearchDirs
108   /// consecutively. Requests for <x> search the current dir first, then each
109   /// directory in SearchDirs, starting at AngledDirIdx, consecutively.  If
110   /// NoCurDirSearch is true, then the check for the file in the current
111   /// directory is suppressed.
112   std::vector<DirectoryLookup> SearchDirs;
113   unsigned AngledDirIdx;
114   unsigned SystemDirIdx;
115   bool NoCurDirSearch;
116 
117   /// FileInfo - This contains all of the preprocessor-specific data about files
118   /// that are included.  The vector is indexed by the FileEntry's UID.
119   ///
120   std::vector<HeaderFileInfo> FileInfo;
121 
122   /// LookupFileCache - This is keeps track of each lookup performed by
123   /// LookupFile.  The first part of the value is the starting index in
124   /// SearchDirs that the cached search was performed from.  If there is a hit
125   /// and this value doesn't match the current query, the cache has to be
126   /// ignored.  The second value is the entry in SearchDirs that satisfied the
127   /// query.
128   llvm::StringMap<std::pair<unsigned, unsigned> > LookupFileCache;
129 
130 
131   /// FrameworkMap - This is a collection mapping a framework or subframework
132   /// name like "Carbon" to the Carbon.framework directory.
133   llvm::StringMap<const DirectoryEntry *> FrameworkMap;
134 
135   /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
136   /// headermaps.  This vector owns the headermap.
137   std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
138 
139   /// \brief Entity used to resolve the identifier IDs of controlling
140   /// macros into IdentifierInfo pointers, as needed.
141   ExternalIdentifierLookup *ExternalLookup;
142 
143   /// \brief Entity used to look up stored header file information.
144   ExternalHeaderFileInfoSource *ExternalSource;
145 
146   // Various statistics we track for performance analysis.
147   unsigned NumIncluded;
148   unsigned NumMultiIncludeFileOptzn;
149   unsigned NumFrameworkLookups, NumSubFrameworkLookups;
150 
151   // HeaderSearch doesn't support default or copy construction.
152   explicit HeaderSearch();
153   explicit HeaderSearch(const HeaderSearch&);
154   void operator=(const HeaderSearch&);
155 public:
156   HeaderSearch(FileManager &FM);
157   ~HeaderSearch();
158 
getFileMgr()159   FileManager &getFileMgr() const { return FileMgr; }
160 
161   /// SetSearchPaths - Interface for setting the file search paths.
162   ///
SetSearchPaths(const std::vector<DirectoryLookup> & dirs,unsigned angledDirIdx,unsigned systemDirIdx,bool noCurDirSearch)163   void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
164                       unsigned angledDirIdx, unsigned systemDirIdx,
165                       bool noCurDirSearch) {
166     assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
167         "Directory indicies are unordered");
168     SearchDirs = dirs;
169     AngledDirIdx = angledDirIdx;
170     SystemDirIdx = systemDirIdx;
171     NoCurDirSearch = noCurDirSearch;
172     //LookupFileCache.clear();
173   }
174 
175   /// ClearFileInfo - Forget everything we know about headers so far.
ClearFileInfo()176   void ClearFileInfo() {
177     FileInfo.clear();
178   }
179 
SetExternalLookup(ExternalIdentifierLookup * EIL)180   void SetExternalLookup(ExternalIdentifierLookup *EIL) {
181     ExternalLookup = EIL;
182   }
183 
getExternalLookup()184   ExternalIdentifierLookup *getExternalLookup() const {
185     return ExternalLookup;
186   }
187 
188   /// \brief Set the external source of header information.
SetExternalSource(ExternalHeaderFileInfoSource * ES)189   void SetExternalSource(ExternalHeaderFileInfoSource *ES) {
190     ExternalSource = ES;
191   }
192 
193   /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
194   /// return null on failure.
195   ///
196   /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member
197   /// the file was found in, or null if not applicable.
198   ///
199   /// \param isAngled indicates whether the file reference is a <> reference.
200   ///
201   /// \param CurDir If non-null, the file was found in the specified directory
202   /// search location.  This is used to implement #include_next.
203   ///
204   /// \param CurFileEnt If non-null, indicates where the #including file is, in
205   /// case a relative search is needed.
206   ///
207   /// \param SearchPath If non-null, will be set to the search path relative
208   /// to which the file was found. If the include path is absolute, SearchPath
209   /// will be set to an empty string.
210   ///
211   /// \param RelativePath If non-null, will be set to the path relative to
212   /// SearchPath at which the file was found. This only differs from the
213   /// Filename for framework includes.
214   const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled,
215                               const DirectoryLookup *FromDir,
216                               const DirectoryLookup *&CurDir,
217                               const FileEntry *CurFileEnt,
218                               llvm::SmallVectorImpl<char> *SearchPath,
219                               llvm::SmallVectorImpl<char> *RelativePath);
220 
221   /// LookupSubframeworkHeader - Look up a subframework for the specified
222   /// #include file.  For example, if #include'ing <HIToolbox/HIToolbox.h> from
223   /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
224   /// is a subframework within Carbon.framework.  If so, return the FileEntry
225   /// for the designated file, otherwise return null.
226   const FileEntry *LookupSubframeworkHeader(
227       llvm::StringRef Filename,
228       const FileEntry *RelativeFileEnt,
229       llvm::SmallVectorImpl<char> *SearchPath,
230       llvm::SmallVectorImpl<char> *RelativePath);
231 
232   /// LookupFrameworkCache - Look up the specified framework name in our
233   /// framework cache, returning the DirectoryEntry it is in if we know,
234   /// otherwise, return null.
LookupFrameworkCache(llvm::StringRef FWName)235   const DirectoryEntry *&LookupFrameworkCache(llvm::StringRef FWName) {
236     return FrameworkMap.GetOrCreateValue(FWName).getValue();
237   }
238 
239   /// ShouldEnterIncludeFile - Mark the specified file as a target of of a
240   /// #include, #include_next, or #import directive.  Return false if #including
241   /// the file will have no effect or true if we should include it.
242   bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport);
243 
244 
245   /// getFileDirFlavor - Return whether the specified file is a normal header,
246   /// a system header, or a C++ friendly system header.
getFileDirFlavor(const FileEntry * File)247   SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) {
248     return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
249   }
250 
251   /// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g.
252   /// due to #pragma once.
MarkFileIncludeOnce(const FileEntry * File)253   void MarkFileIncludeOnce(const FileEntry *File) {
254     HeaderFileInfo &FI = getFileInfo(File);
255     FI.isImport = true;
256     FI.isPragmaOnce = true;
257   }
258 
259   /// MarkFileSystemHeader - Mark the specified file as a system header, e.g.
260   /// due to #pragma GCC system_header.
MarkFileSystemHeader(const FileEntry * File)261   void MarkFileSystemHeader(const FileEntry *File) {
262     getFileInfo(File).DirInfo = SrcMgr::C_System;
263   }
264 
265   /// IncrementIncludeCount - Increment the count for the number of times the
266   /// specified FileEntry has been entered.
IncrementIncludeCount(const FileEntry * File)267   void IncrementIncludeCount(const FileEntry *File) {
268     ++getFileInfo(File).NumIncludes;
269   }
270 
271   /// SetFileControllingMacro - Mark the specified file as having a controlling
272   /// macro.  This is used by the multiple-include optimization to eliminate
273   /// no-op #includes.
SetFileControllingMacro(const FileEntry * File,const IdentifierInfo * ControllingMacro)274   void SetFileControllingMacro(const FileEntry *File,
275                                const IdentifierInfo *ControllingMacro) {
276     getFileInfo(File).ControllingMacro = ControllingMacro;
277   }
278 
279   /// \brief Determine whether this file is intended to be safe from
280   /// multiple inclusions, e.g., it has #pragma once or a controlling
281   /// macro.
282   ///
283   /// This routine does not consider the effect of #import
284   bool isFileMultipleIncludeGuarded(const FileEntry *File);
285 
286   /// CreateHeaderMap - This method returns a HeaderMap for the specified
287   /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
288   const HeaderMap *CreateHeaderMap(const FileEntry *FE);
289 
IncrementFrameworkLookupCount()290   void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
291 
292   typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator;
header_file_begin()293   header_file_iterator header_file_begin() const { return FileInfo.begin(); }
header_file_end()294   header_file_iterator header_file_end() const { return FileInfo.end(); }
header_file_size()295   unsigned header_file_size() const { return FileInfo.size(); }
296 
297   // Used by ASTReader.
298   void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
299 
300   // Used by external tools
301   typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator;
search_dir_begin()302   search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); }
search_dir_end()303   search_dir_iterator search_dir_end() const { return SearchDirs.end(); }
search_dir_size()304   unsigned search_dir_size() const { return SearchDirs.size(); }
305 
quoted_dir_begin()306   search_dir_iterator quoted_dir_begin() const {
307     return SearchDirs.begin();
308   }
quoted_dir_end()309   search_dir_iterator quoted_dir_end() const {
310     return SearchDirs.begin() + AngledDirIdx;
311   }
312 
angled_dir_begin()313   search_dir_iterator angled_dir_begin() const {
314     return SearchDirs.begin() + AngledDirIdx;
315   }
angled_dir_end()316   search_dir_iterator angled_dir_end() const {
317     return SearchDirs.begin() + SystemDirIdx;
318   }
319 
system_dir_begin()320   search_dir_iterator system_dir_begin() const {
321     return SearchDirs.begin() + SystemDirIdx;
322   }
system_dir_end()323   search_dir_iterator system_dir_end() const { return SearchDirs.end(); }
324 
325   void PrintStats();
326 private:
327 
328   /// getFileInfo - Return the HeaderFileInfo structure for the specified
329   /// FileEntry.
330   HeaderFileInfo &getFileInfo(const FileEntry *FE);
331 };
332 
333 }  // end namespace clang
334 
335 #endif
336