zcov: / lib/Lex/HeaderSearch.cpp


Files: 1 Branches Taken: 39.8% 47 / 118
Generated: 2010-02-10 01:31 Branches Executed: 49.2% 58 / 118
Line Coverage: 58.7% 105 / 179


Programs: 2 Runs 3018


       1                 : //===--- HeaderSearch.cpp - Resolve Header File Locations ---===//
       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 implements the DirectoryLookup and HeaderSearch interfaces.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Lex/HeaderSearch.h"
      15                 : #include "clang/Lex/HeaderMap.h"
      16                 : #include "clang/Basic/FileManager.h"
      17                 : #include "clang/Basic/IdentifierTable.h"
      18                 : #include "llvm/System/Path.h"
      19                 : #include "llvm/ADT/SmallString.h"
      20                 : #include <cstdio>
      21                 : using namespace clang;
      22                 : 
      23                 : const IdentifierInfo *
      24              681: HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
                      118: branch 0 taken
                      563: branch 1 taken
      25              681:   if (ControllingMacro)
      26              118:     return ControllingMacro;
      27                 : 
                        1: branch 0 taken
                      562: branch 1 taken
                        0: branch 2 not taken
                        1: branch 3 taken
      28              563:   if (!ControllingMacroID || !External)
      29              562:     return 0;
      30                 : 
      31                1:   ControllingMacro = External->GetIdentifier(ControllingMacroID);
      32                1:   return ControllingMacro;
      33                 : }
      34                 : 
      35             2533: HeaderSearch::HeaderSearch(FileManager &FM) : FileMgr(FM), FrameworkMap(64) {
      36             2533:   SystemDirIdx = 0;
      37             2533:   NoCurDirSearch = false;
      38                 : 
      39             2533:   ExternalLookup = 0;
      40             2533:   NumIncluded = 0;
      41             2533:   NumMultiIncludeFileOptzn = 0;
      42             2533:   NumFrameworkLookups = NumSubFrameworkLookups = 0;
      43             2533: }
      44                 : 
      45             2530: HeaderSearch::~HeaderSearch() {
      46                 :   // Delete headermaps.
                        0: branch 1 not taken
                     2530: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
      47             2530:   for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
      48                0:     delete HeaderMaps[i].second;
      49             2530: }
      50                 : 
      51                2: void HeaderSearch::PrintStats() {
      52                2:   fprintf(stderr, "\n*** HeaderSearch Stats:\n");
      53                2:   fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size());
      54                2:   unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0;
                        2: branch 1 taken
                        2: branch 2 taken
      55                4:   for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) {
      56                2:     NumOnceOnlyFiles += FileInfo[i].isImport;
                        2: branch 1 taken
                        0: branch 2 not taken
      57                2:     if (MaxNumIncludes < FileInfo[i].NumIncludes)
      58                2:       MaxNumIncludes = FileInfo[i].NumIncludes;
      59                2:     NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1;
      60                 :   }
      61                2:   fprintf(stderr, "  %d #import/#pragma once files.\n", NumOnceOnlyFiles);
      62                2:   fprintf(stderr, "  %d included exactly once.\n", NumSingleIncludedFiles);
      63                2:   fprintf(stderr, "  %d max times a file is included.\n", MaxNumIncludes);
      64                 : 
      65                2:   fprintf(stderr, "  %d #include/#include_next/#import.\n", NumIncluded);
      66                 :   fprintf(stderr, "    %d #includes skipped due to"
      67                2:           " the multi-include optimization.\n", NumMultiIncludeFileOptzn);
      68                 : 
      69                2:   fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups);
      70                2:   fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups);
      71                2: }
      72                 : 
      73                 : /// CreateHeaderMap - This method returns a HeaderMap for the specified
      74                 : /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
      75                0: const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
      76                 :   // We expect the number of headermaps to be small, and almost always empty.
      77                 :   // If it ever grows, use of a linear search should be re-evaluated.
                        0: branch 1 not taken
                        0: branch 2 not taken
      78                0:   if (!HeaderMaps.empty()) {
                        0: branch 1 not taken
                        0: branch 2 not taken
      79                0:     for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
      80                 :       // Pointer equality comparison of FileEntries works because they are
      81                 :       // already uniqued by inode.
                        0: branch 1 not taken
                        0: branch 2 not taken
      82                0:       if (HeaderMaps[i].first == FE)
      83                0:         return HeaderMaps[i].second;
      84                 :   }
      85                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
      86                0:   if (const HeaderMap *HM = HeaderMap::Create(FE)) {
      87                0:     HeaderMaps.push_back(std::make_pair(FE, HM));
      88                0:     return HM;
      89                 :   }
      90                 : 
      91                0:   return 0;
      92                 : }
      93                 : 
      94                 : //===----------------------------------------------------------------------===//
      95                 : // File lookup within a DirectoryLookup scope
      96                 : //===----------------------------------------------------------------------===//
      97                 : 
      98                 : /// getName - Return the directory or filename corresponding to this lookup
      99                 : /// object.
     100                3: const char *DirectoryLookup::getName() const {
                        3: branch 1 taken
                        0: branch 2 not taken
     101                3:   if (isNormalDir())
     102                3:     return getDir()->getName();
                        0: branch 1 not taken
                        0: branch 2 not taken
     103                0:   if (isFramework())
     104                0:     return getFrameworkDir()->getName();
                        0: branch 1 not taken
                        0: branch 2 not taken
     105                0:   assert(isHeaderMap() && "Unknown DirectoryLookup");
     106                0:   return getHeaderMap()->getFileName();
     107                 : }
     108                 : 
     109                 : 
     110                 : /// LookupFile - Lookup the specified file in this search path, returning it
     111                 : /// if it exists or returning null if not.
     112                 : const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename,
     113             1502:                                              HeaderSearch &HS) const {
     114             1502:   llvm::SmallString<1024> TmpDir;
                     1502: branch 1 taken
                        0: branch 2 not taken
     115             1502:   if (isNormalDir()) {
     116                 :     // Concatenate the requested file onto the directory.
     117                 :     // FIXME: Portability.  Filename concatenation should be in sys::Path.
     118             1502:     TmpDir += getDir()->getName();
     119             1502:     TmpDir.push_back('/');
     120             1502:     TmpDir.append(Filename.begin(), Filename.end());
     121             1502:     return HS.getFileMgr().getFile(TmpDir.begin(), TmpDir.end());
     122                 :   }
     123                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     124                0:   if (isFramework())
     125                0:     return DoFrameworkLookup(Filename, HS);
     126                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     127                0:   assert(isHeaderMap() && "Unknown directory lookup");
     128             1502:   return getHeaderMap()->LookupFile(Filename, HS.getFileMgr());
     129                 : }
     130                 : 
     131                 : 
     132                 : /// DoFrameworkLookup - Do a lookup of the specified file in the current
     133                 : /// DirectoryLookup, which is a framework directory.
     134                 : const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename,
     135                0:                                                     HeaderSearch &HS) const {
     136                0:   FileManager &FileMgr = HS.getFileMgr();
     137                 : 
     138                 :   // Framework names must have a '/' in the filename.
     139                0:   size_t SlashPos = Filename.find('/');
                        0: branch 0 not taken
                        0: branch 1 not taken
     140                0:   if (SlashPos == llvm::StringRef::npos) return 0;
     141                 : 
     142                 :   // Find out if this is the home for the specified framework, by checking
     143                 :   // HeaderSearch.  Possible answer are yes/no and unknown.
     144                 :   const DirectoryEntry *&FrameworkDirCache =
     145                0:     HS.LookupFrameworkCache(Filename.substr(0, SlashPos));
     146                 : 
     147                 :   // If it is known and in some other directory, fail.
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     148                0:   if (FrameworkDirCache && FrameworkDirCache != getFrameworkDir())
     149                0:     return 0;
     150                 : 
     151                 :   // Otherwise, construct the path to this framework dir.
     152                 : 
     153                 :   // FrameworkName = "/System/Library/Frameworks/"
     154                0:   llvm::SmallString<1024> FrameworkName;
     155                0:   FrameworkName += getFrameworkDir()->getName();
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
     156                0:   if (FrameworkName.empty() || FrameworkName.back() != '/')
     157                0:     FrameworkName.push_back('/');
     158                 : 
     159                 :   // FrameworkName = "/System/Library/Frameworks/Cocoa"
     160                0:   FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
     161                 : 
     162                 :   // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
     163                0:   FrameworkName += ".framework/";
     164                 : 
     165                 :   // If the cache entry is still unresolved, query to see if the cache entry is
     166                 :   // still unresolved.  If so, check its existence now.
                        0: branch 0 not taken
                        0: branch 1 not taken
     167                0:   if (FrameworkDirCache == 0) {
     168                0:     HS.IncrementFrameworkLookupCount();
     169                 : 
     170                 :     // If the framework dir doesn't exist, we fail.
     171                 :     // FIXME: It's probably more efficient to query this with FileMgr.getDir.
                        0: branch 10 not taken
                        0: branch 11 not taken
     172                0:     if (!llvm::sys::Path(std::string(FrameworkName.begin(),
     173                 :                                      FrameworkName.end())).exists())
     174                0:       return 0;
     175                 : 
     176                 :     // Otherwise, if it does, remember that this is the right direntry for this
     177                 :     // framework.
     178                0:     FrameworkDirCache = getFrameworkDir();
     179                 :   }
     180                 : 
     181                 :   // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
     182                0:   unsigned OrigSize = FrameworkName.size();
     183                 : 
     184                0:   FrameworkName += "Headers/";
     185                0:   FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
                        0: branch 0 not taken
                        0: branch 1 not taken
     186                0:   if (const FileEntry *FE = FileMgr.getFile(FrameworkName.begin(),
     187                0:                                             FrameworkName.end())) {
     188                0:     return FE;
     189                 :   }
     190                 : 
     191                 :   // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
     192                0:   const char *Private = "Private";
     193                 :   FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
     194                0:                        Private+strlen(Private));
     195                0:   return FileMgr.getFile(FrameworkName.begin(), FrameworkName.end());
     196                 : }
     197                 : 
     198                 : 
     199                 : //===----------------------------------------------------------------------===//
     200                 : // Header File Location.
     201                 : //===----------------------------------------------------------------------===//
     202                 : 
     203                 : 
     204                 : /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
     205                 : /// return null on failure.  isAngled indicates whether the file reference is
     206                 : /// for system #include's or not (i.e. using <> instead of "").  CurFileEnt, if
     207                 : /// non-null, indicates where the #including file is, in case a relative search
     208                 : /// is needed.
     209                 : const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename,
     210                 :                                           bool isAngled,
     211                 :                                           const DirectoryLookup *FromDir,
     212                 :                                           const DirectoryLookup *&CurDir,
     213              727:                                           const FileEntry *CurFileEnt) {
     214                 :   // If 'Filename' is absolute, check to see if it exists and no searching.
                       31: branch 3 taken
                      696: branch 4 taken
     215              727:   if (llvm::sys::Path::isAbsolute(Filename.begin(), Filename.size())) {
     216               31:     CurDir = 0;
     217                 : 
     218                 :     // If this was an #include_next "/absolute/file", fail.
                        0: branch 0 not taken
                       31: branch 1 taken
     219               31:     if (FromDir) return 0;
     220                 : 
     221                 :     // Otherwise, just return the file.
     222               31:     return FileMgr.getFile(Filename);
     223                 :   }
     224                 : 
     225                 :   // Step #0, unless disabled, check to see if the file is in the #includer's
     226                 :   // directory.  This has to be based on CurFileEnt, not CurDir, because
     227                 :   // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and
     228                 :   // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h".
     229                 :   // This search is not done for <> headers.
                      652: branch 0 taken
                       44: branch 1 taken
                       63: branch 2 taken
                      589: branch 3 taken
                       63: branch 4 taken
                        0: branch 5 not taken
     230              696:   if (CurFileEnt && !isAngled && !NoCurDirSearch) {
     231               63:     llvm::SmallString<1024> TmpDir;
     232                 :     // Concatenate the requested file onto the directory.
     233                 :     // FIXME: Portability.  Filename concatenation should be in sys::Path.
     234               63:     TmpDir += CurFileEnt->getDir()->getName();
     235               63:     TmpDir.push_back('/');
     236               63:     TmpDir.append(Filename.begin(), Filename.end());
                       48: branch 2 taken
                       15: branch 3 taken
     237               63:     if (const FileEntry *FE = FileMgr.getFile(TmpDir.str())) {
     238                 :       // Leave CurDir unset.
     239                 :       // This file is a system header or C++ unfriendly if the old file is.
     240                 :       //
     241                 :       // Note that the temporary 'DirInfo' is required here, as either call to
     242                 :       // getFileInfo could resize the vector and we don't want to rely on order
     243                 :       // of evaluation.
     244               48:       unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo;
     245               48:       getFileInfo(FE).DirInfo = DirInfo;
     246               96:       return FE;
                       15: branch 1 taken
                       48: branch 2 taken
     247               63:     }
     248                 :   }
     249                 : 
     250              648:   CurDir = 0;
     251                 : 
     252                 :   // If this is a system #include, ignore the user #include locs.
                      633: branch 0 taken
                       15: branch 1 taken
     253              648:   unsigned i = isAngled ? SystemDirIdx : 0;
     254                 : 
     255                 :   // If this is a #include_next request, start searching after the directory the
     256                 :   // file was found in.
                       43: branch 0 taken
                      605: branch 1 taken
     257              648:   if (FromDir)
     258               43:     i = FromDir-&SearchDirs[0];
     259                 : 
     260                 :   // Cache all of the lookups performed by this method.  Many headers are
     261                 :   // multiply included, and the "pragma once" optimization prevents them from
     262                 :   // being relex/pp'd, but they would still have to search through a
     263                 :   // (potentially huge) series of SearchDirs to find it.
     264                 :   std::pair<unsigned, unsigned> &CacheLookup =
     265              648:     LookupFileCache.GetOrCreateValue(Filename).getValue();
     266                 : 
     267                 :   // If the entry has been previously looked up, the first value will be
     268                 :   // non-zero.  If the value is equal to i (the start point of our search), then
     269                 :   // this is a matching hit.
                      203: branch 0 taken
                      445: branch 1 taken
     270              648:   if (CacheLookup.first == i+1) {
     271                 :     // Skip querying potentially lots of directories for this lookup.
     272              203:     i = CacheLookup.second;
     273                 :   } else {
     274                 :     // Otherwise, this is the first query, or the previous query didn't match
     275                 :     // our search start.  We will fill in our found location below, so prime the
     276                 :     // start point value.
     277              445:     CacheLookup.first = i+1;
     278                 :   }
     279                 : 
     280                 :   // Check each directory in sequence to see if it contains this file.
                     1502: branch 1 taken
                        7: branch 2 taken
     281             1509:   for (; i != SearchDirs.size(); ++i) {
     282                 :     const FileEntry *FE =
     283             1502:       SearchDirs[i].LookupFile(Filename, *this);
                      641: branch 0 taken
                      861: branch 1 taken
     284             1502:     if (!FE) continue;
     285                 : 
     286              641:     CurDir = &SearchDirs[i];
     287                 : 
     288                 :     // This file is a system header or C++ unfriendly if the dir is.
     289              641:     getFileInfo(FE).DirInfo = CurDir->getDirCharacteristic();
     290                 : 
     291                 :     // Remember this location for the next lookup we do.
     292              641:     CacheLookup.second = i;
     293              641:     return FE;
     294                 :   }
     295                 : 
     296                 :   // Otherwise, didn't find it. Remember we didn't find this.
     297                7:   CacheLookup.second = SearchDirs.size();
     298                7:   return 0;
     299                 : }
     300                 : 
     301                 : /// LookupSubframeworkHeader - Look up a subframework for the specified
     302                 : /// #include file.  For example, if #include'ing <HIToolbox/HIToolbox.h> from
     303                 : /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
     304                 : /// is a subframework within Carbon.framework.  If so, return the FileEntry
     305                 : /// for the designated file, otherwise return null.
     306                 : const FileEntry *HeaderSearch::
     307                 : LookupSubframeworkHeader(llvm::StringRef Filename,
     308                7:                          const FileEntry *ContextFileEnt) {
                        0: branch 0 not taken
                        7: branch 1 taken
     309                7:   assert(ContextFileEnt && "No context file?");
     310                 : 
     311                 :   // Framework names must have a '/' in the filename.  Find it.
     312                7:   size_t SlashPos = Filename.find('/');
                        7: branch 0 taken
                        0: branch 1 not taken
     313                7:   if (SlashPos == llvm::StringRef::npos) return 0;
     314                 : 
     315                 :   // Look up the base framework name of the ContextFileEnt.
     316                0:   const char *ContextName = ContextFileEnt->getName();
     317                 : 
     318                 :   // If the context info wasn't a framework, couldn't be a subframework.
     319                0:   const char *FrameworkPos = strstr(ContextName, ".framework/");
                        0: branch 0 not taken
                        0: branch 1 not taken
     320                0:   if (FrameworkPos == 0)
     321                0:     return 0;
     322                 : 
     323                 :   llvm::SmallString<1024> FrameworkName(ContextName,
     324                0:                                         FrameworkPos+strlen(".framework/"));
     325                 : 
     326                 :   // Append Frameworks/HIToolbox.framework/
     327                0:   FrameworkName += "Frameworks/";
     328                0:   FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
     329                0:   FrameworkName += ".framework/";
     330                 : 
     331                 :   llvm::StringMapEntry<const DirectoryEntry *> &CacheLookup =
     332                0:     FrameworkMap.GetOrCreateValue(Filename.begin(), Filename.begin()+SlashPos);
     333                 : 
     334                 :   // Some other location?
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 11 not taken
                        0: branch 12 not taken
                        0: branch 13 not taken
                        0: branch 14 not taken
     335                0:   if (CacheLookup.getValue() &&
     336                 :       CacheLookup.getKeyLength() == FrameworkName.size() &&
     337                 :       memcmp(CacheLookup.getKeyData(), &FrameworkName[0],
     338                 :              CacheLookup.getKeyLength()) != 0)
     339                0:     return 0;
     340                 : 
     341                 :   // Cache subframework.
                        0: branch 1 not taken
                        0: branch 2 not taken
     342                0:   if (CacheLookup.getValue() == 0) {
     343                0:     ++NumSubFrameworkLookups;
     344                 : 
     345                 :     // If the framework dir doesn't exist, we fail.
     346                 :     const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.begin(),
     347                0:                                                      FrameworkName.end());
                        0: branch 0 not taken
                        0: branch 1 not taken
     348                0:     if (Dir == 0) return 0;
     349                 : 
     350                 :     // Otherwise, if it does, remember that this is the right direntry for this
     351                 :     // framework.
     352                0:     CacheLookup.setValue(Dir);
     353                 :   }
     354                 : 
     355                0:   const FileEntry *FE = 0;
     356                 : 
     357                 :   // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
     358                0:   llvm::SmallString<1024> HeadersFilename(FrameworkName);
     359                0:   HeadersFilename += "Headers/";
     360                0:   HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
                        0: branch 3 not taken
                        0: branch 4 not taken
     361                0:   if (!(FE = FileMgr.getFile(HeadersFilename.begin(),
     362                 :                              HeadersFilename.end()))) {
     363                 : 
     364                 :     // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
     365                0:     HeadersFilename = FrameworkName;
     366                0:     HeadersFilename += "PrivateHeaders/";
     367                0:     HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
                        0: branch 3 not taken
                        0: branch 4 not taken
     368                0:     if (!(FE = FileMgr.getFile(HeadersFilename.begin(), HeadersFilename.end())))
     369                0:       return 0;
     370                 :   }
     371                 : 
     372                 :   // This file is a system header or C++ unfriendly if the old file is.
     373                 :   //
     374                 :   // Note that the temporary 'DirInfo' is required here, as either call to
     375                 :   // getFileInfo could resize the vector and we don't want to rely on order
     376                 :   // of evaluation.
     377                0:   unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo;
     378                0:   getFileInfo(FE).DirInfo = DirInfo;
     379                0:   return FE;
     380                 : }
     381                 : 
     382                 : //===----------------------------------------------------------------------===//
     383                 : // File Info Management.
     384                 : //===----------------------------------------------------------------------===//
     385                 : 
     386                 : 
     387                 : /// getFileInfo - Return the HeaderFileInfo structure for the specified
     388                 : /// FileEntry.
     389             4695: HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
                     2927: branch 2 taken
                     1768: branch 3 taken
     390             4695:   if (FE->getUID() >= FileInfo.size())
     391             2927:     FileInfo.resize(FE->getUID()+1);
     392             4695:   return FileInfo[FE->getUID()];
     393                 : }
     394                 : 
     395               56: void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) {
                       56: branch 1 taken
                        0: branch 2 not taken
     396               56:   if (UID >= FileInfo.size())
     397               56:     FileInfo.resize(UID+1);
     398               56:   FileInfo[UID] = HFI;
     399               56: }
     400                 : 
     401                 : /// ShouldEnterIncludeFile - Mark the specified file as a target of of a
     402                 : /// #include, #include_next, or #import directive.  Return false if #including
     403                 : /// the file will have no effect or true if we should include it.
     404              684: bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
     405              684:   ++NumIncluded; // Count # of attempted #includes.
     406                 : 
     407                 :   // Get information about this file.
     408              684:   HeaderFileInfo &FileInfo = getFileInfo(File);
     409                 : 
     410                 :   // If this is a #import directive, check that we have not already imported
     411                 :   // this header.
                        4: branch 0 taken
                      680: branch 1 taken
     412              684:   if (isImport) {
     413                 :     // If this has already been imported, don't import it again.
     414                4:     FileInfo.isImport = true;
     415                 : 
     416                 :     // Has this already been #import'ed or #include'd?
                        3: branch 0 taken
                        1: branch 1 taken
     417                4:     if (FileInfo.NumIncludes) return false;
     418                 :   } else {
     419                 :     // Otherwise, if this is a #include of a file that was previously #import'd
     420                 :     // or if this is the second #include of a #pragma once file, ignore it.
                        0: branch 0 not taken
                      680: branch 1 taken
     421              680:     if (FileInfo.isImport)
     422                0:       return false;
     423                 :   }
     424                 : 
     425                 :   // Next, check to see if the file is wrapped with #ifndef guards.  If so, and
     426                 :   // if the macro that guards it is defined, we know the #include has no effect.
                      119: branch 0 taken
                      562: branch 1 taken
     427              681:   if (const IdentifierInfo *ControllingMacro
     428              681:       = FileInfo.getControllingMacro(ExternalLookup))
                      113: branch 1 taken
                        6: branch 2 taken
     429              119:     if (ControllingMacro->hasMacroDefinition()) {
     430              113:       ++NumMultiIncludeFileOptzn;
     431              113:       return false;
     432                 :     }
     433                 : 
     434                 :   // Increment the number of times this file has been included.
     435              568:   ++FileInfo.NumIncludes;
     436                 : 
     437              568:   return true;
     438                 : }
     439                 : 
     440                 : 

Generated: 2010-02-10 01:31 by zcov