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 71 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. 82 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 159 FileManager &getFileMgr() const { return FileMgr; } 160 161 /// SetSearchPaths - Interface for setting the file search paths. 162 /// 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. 176 void ClearFileInfo() { 177 FileInfo.clear(); 178 } 179 180 void SetExternalLookup(ExternalIdentifierLookup *EIL) { 181 ExternalLookup = EIL; 182 } 183 184 ExternalIdentifierLookup *getExternalLookup() const { 185 return ExternalLookup; 186 } 187 188 /// \brief Set the external source of header information. 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. 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. 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. 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. 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. 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. 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 290 void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; } 291 292 typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator; 293 header_file_iterator header_file_begin() const { return FileInfo.begin(); } 294 header_file_iterator header_file_end() const { return FileInfo.end(); } 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; 302 search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); } 303 search_dir_iterator search_dir_end() const { return SearchDirs.end(); } 304 unsigned search_dir_size() const { return SearchDirs.size(); } 305 306 search_dir_iterator quoted_dir_begin() const { 307 return SearchDirs.begin(); 308 } 309 search_dir_iterator quoted_dir_end() const { 310 return SearchDirs.begin() + AngledDirIdx; 311 } 312 313 search_dir_iterator angled_dir_begin() const { 314 return SearchDirs.begin() + AngledDirIdx; 315 } 316 search_dir_iterator angled_dir_end() const { 317 return SearchDirs.begin() + SystemDirIdx; 318 } 319 320 search_dir_iterator system_dir_begin() const { 321 return SearchDirs.begin() + SystemDirIdx; 322 } 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