[cfe-commits] r45092 - in /cfe/trunk: Driver/clang.cpp Lex/HeaderSearch.cpp include/clang/Lex/DirectoryLookup.h

Chris Lattner sabre at nondot.org
Sun Dec 16 23:52:41 PST 2007


Author: lattner
Date: Mon Dec 17 01:52:39 2007
New Revision: 45092

URL: http://llvm.org/viewvc/llvm-project?rev=45092&view=rev
Log:
as it turns out, frameworks and headermaps are orthogonal.  Make this so in
the internal representation.  This also fixes a bug where -I foo  -F foo would
not search foo as both a normal and framework include dir.

Modified:
    cfe/trunk/Driver/clang.cpp
    cfe/trunk/Lex/HeaderSearch.cpp
    cfe/trunk/include/clang/Lex/DirectoryLookup.h

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=45092&r1=45091&r2=45092&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Mon Dec 17 01:52:39 2007
@@ -651,22 +651,24 @@
     return;
   }
   
-  // Check to see if this is an apple-style headermap.
-  if (const FileEntry *FE = FM.getFile(&MappedPath[0], 
-                                       &MappedPath[0]+MappedPath.size())) {
-    std::string ErrorInfo;
-    const HeaderMap *HM = HS.CreateHeaderMap(FE, ErrorInfo);
-    if (HM) {
-      IncludeGroup[Group].push_back(DirectoryLookup(HM, Type, isUserSupplied,
-                                                    isFramework));
-      return;
-    }
-    
-    // If this looked like a headermap but was corrupted, emit that error,
-    // otherwise treat it as a missing directory.
-    if (!ErrorInfo.empty()) {
-      fprintf(stderr, "%s\n", ErrorInfo.c_str());
-      return;
+  // Check to see if this is an apple-style headermap (which are not allowed to
+  // be frameworks).
+  if (!isFramework) {
+    if (const FileEntry *FE = FM.getFile(&MappedPath[0], 
+                                         &MappedPath[0]+MappedPath.size())) {
+      std::string ErrorInfo;
+      const HeaderMap *HM = HS.CreateHeaderMap(FE, ErrorInfo);
+      if (HM) {
+        IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
+        return;
+      }
+      
+      // If this looked like a headermap but was corrupted, emit that error,
+      // otherwise treat it as a missing directory.
+      if (!ErrorInfo.empty()) {
+        fprintf(stderr, "%s\n", ErrorInfo.c_str());
+        return;
+      }
     }
   }
   
@@ -678,6 +680,7 @@
 /// search list, remove the later (dead) ones.
 static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList) {
   llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
+  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
   llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
   for (unsigned i = 0; i != SearchList.size(); ++i) {
     if (SearchList[i].isNormalDir()) {
@@ -688,6 +691,15 @@
       if (Verbose)
         fprintf(stderr, "ignoring duplicate directory \"%s\"\n",
                 SearchList[i].getDir()->getName());
+    } else if (SearchList[i].isFramework()) {
+      // If this isn't the first time we've seen this framework dir, remove it.
+      if (SeenFrameworkDirs.insert(SearchList[i].getFrameworkDir()))
+        continue;
+      
+      if (Verbose)
+        fprintf(stderr, "ignoring duplicate framework \"%s\"\n",
+                SearchList[i].getFrameworkDir()->getName());
+      
     } else {
       assert(SearchList[i].isHeaderMap() && "Not a headermap or normal dir?");
       // If this isn't the first time we've seen this headermap, remove it.

Modified: cfe/trunk/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/HeaderSearch.cpp?rev=45092&r1=45091&r2=45092&view=diff

==============================================================================
--- cfe/trunk/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/Lex/HeaderSearch.cpp Mon Dec 17 01:52:39 2007
@@ -61,9 +61,11 @@
 const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE, 
                                                std::string &ErrorInfo) {
   // We expect the number of headermaps to be small, and almost always empty.
-  // If it ever grows, use of a linear search should be reevaluated.
+  // If it ever grows, use of a linear search should be re-evaluated.
   if (!HeaderMaps.empty()) {
     for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
+      // Pointer equality comparison of FileEntries works because they are
+      // already uniqued by inode.
       if (HeaderMaps[i].first == FE) 
         return HeaderMaps[i].second;
   }
@@ -76,6 +78,26 @@
   return 0;
 }
 
+//===----------------------------------------------------------------------===//
+// File lookup within a DirectoryLookup scope
+//===----------------------------------------------------------------------===//
+
+/// LookupFile - Lookup the specified file in this search path, returning it
+/// if it exists or returning null if not.
+const FileEntry *DirectoryLookup::LookupFile(const char *FilenameStart,
+                                             const char *FilenameEnd,
+                                             FileManager &FileMgr) const {
+  llvm::SmallString<1024> TmpDir;
+  
+  // Concatenate the requested file onto the directory.
+  // FIXME: Portability.  Filename concatenation should be in sys::Path.
+  TmpDir += getDir()->getName();
+  TmpDir.push_back('/');
+  TmpDir.append(FilenameStart, FilenameEnd);
+  return FileMgr.getFile(TmpDir.begin(), TmpDir.end());
+}
+
+
 
 //===----------------------------------------------------------------------===//
 // Header File Location.
@@ -137,6 +159,7 @@
   return FileMgr.getFile(FrameworkName.begin(), FrameworkName.end());
 }
 
+
 /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
 /// return null on failure.  isAngled indicates whether the file reference is
 /// for system #include's or not (i.e. using <> instead of "").  CurFileEnt, if
@@ -161,11 +184,13 @@
     return FileMgr.getFile(FilenameStart, FilenameEnd);
   }
   
-  llvm::SmallString<1024> TmpDir;
-  
   // Step #0, unless disabled, check to see if the file is in the #includer's
-  // directory.  This search is not done for <> headers.
+  // directory.  This has to be based on CurFileEnt, not CurDir, because
+  // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and
+  // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h".
+  // This search is not done for <> headers.
   if (CurFileEnt && !isAngled && !NoCurDirSearch) {
+    llvm::SmallString<1024> TmpDir;
     // Concatenate the requested file onto the directory.
     // FIXME: Portability.  Filename concatenation should be in sys::Path.
     TmpDir += CurFileEnt->getDir()->getName();
@@ -173,12 +198,10 @@
     TmpDir.append(FilenameStart, FilenameEnd);
     if (const FileEntry *FE = FileMgr.getFile(TmpDir.begin(), TmpDir.end())) {
       // Leave CurDir unset.
-      
       // This file is a system header or C++ unfriendly if the old file is.
       getFileInfo(FE).DirInfo = getFileInfo(CurFileEnt).DirInfo;
       return FE;
     }
-    TmpDir.clear();
   }
   
   CurDir = 0;
@@ -210,20 +233,15 @@
     // start point value.
     CacheLookup.first = i+1;
   }
-    
+  
   // Check each directory in sequence to see if it contains this file.
   for (; i != SearchDirs.size(); ++i) {
     const FileEntry *FE = 0;
     if (!SearchDirs[i].isFramework()) {
-      // FIXME: Portability.  Adding file to dir should be in sys::Path.
-      // Concatenate the requested file onto the directory.
-      TmpDir.clear();
-      TmpDir += SearchDirs[i].getDir()->getName();
-      TmpDir.push_back('/');
-      TmpDir.append(FilenameStart, FilenameEnd);
-      FE = FileMgr.getFile(TmpDir.begin(), TmpDir.end());
+      FE = SearchDirs[i].LookupFile(FilenameStart, FilenameEnd, FileMgr);
     } else {
-      FE = DoFrameworkLookup(SearchDirs[i].getDir(), FilenameStart,FilenameEnd);
+      FE = DoFrameworkLookup(SearchDirs[i].getFrameworkDir(),
+                             FilenameStart, FilenameEnd);
     }
     
     if (FE) {

Modified: cfe/trunk/include/clang/Lex/DirectoryLookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/DirectoryLookup.h?rev=45092&r1=45091&r2=45092&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/DirectoryLookup.h (original)
+++ cfe/trunk/include/clang/Lex/DirectoryLookup.h Mon Dec 17 01:52:39 2007
@@ -15,14 +15,15 @@
 #define LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
 
 namespace clang {
-class DirectoryEntry;
 class HeaderMap;
+class DirectoryEntry;
+class FileEntry;
+class FileManager;
 
 /// DirectoryLookup - This class represents one entry in the search list that
 /// specifies the search order for directories in #include directives.  It
-/// represents either a directory or a 'headermap'.  A headermap is just like a
-/// directory, but it remaps its contents through an indirection table instead
-/// of indexing a directory.
+/// represents either a directory, a framework, or a headermap.
+///
 class DirectoryLookup {
 public:
   enum DirType {
@@ -30,14 +31,20 @@
     SystemHeaderDir,
     ExternCSystemHeaderDir
   };
+  
+  enum LookupType_t {
+    LT_NormalDir,
+    LT_Framework,
+    LT_HeaderMap
+  };
 private:
   union {  // This union is discriminated by isHeaderMap.
-    /// Dir - This is the actual directory that we're referring to.
-    ///
+    /// Dir - This is the actual directory that we're referring to for a normal
+    /// directory or a framework.
     const DirectoryEntry *Dir;
   
-    /// Map - This is the HeaderMap corresponding if the isHeaderMap field is
-    /// true.
+    /// Map - This is the HeaderMap if this is a headermap lookup.
+    ///
     const HeaderMap *Map;
   } u;
   
@@ -49,44 +56,57 @@
   ///
   bool UserSupplied : 1;
   
-  /// Framework - True if this is a framework directory search-path.
-  ///
-  bool Framework : 1;
-  
-  /// IsHeaderMap - True if the HeaderMap field is valid, false if the Dir field
-  /// is valid.
-  bool IsHeaderMap : 1;
+  /// LookupType - This indicates whether this DirectoryLookup object is a
+  /// normal directory, a framework, or a headermap.
+  unsigned LookupType : 2;
 public:
   /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
   /// 'dir'.
   DirectoryLookup(const DirectoryEntry *dir, DirType DT, bool isUser,
                   bool isFramework)
     : DirCharacteristic(DT), UserSupplied(isUser),
-      Framework(isFramework), IsHeaderMap(false) {
+     LookupType(isFramework ? LT_Framework : LT_NormalDir) {
     u.Dir = dir; 
   }
   
   /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
   /// 'map'.
-  DirectoryLookup(const HeaderMap *map, DirType DT, bool isUser, bool isFWork)
-    : DirCharacteristic(DT), UserSupplied(isUser), Framework(isFWork), 
-      IsHeaderMap(true) {
+  DirectoryLookup(const HeaderMap *map, DirType DT, bool isUser)
+    : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap) {
     u.Map = map; 
   }
   
+  /// LookupFile - Lookup the specified file in this search path, returning it
+  /// if it exists or returning null if not.
+  const FileEntry *LookupFile(const char *FilenameStart,
+                              const char *FilenameEnd,
+                              FileManager &FileMgr) const;
+  
   /// getDir - Return the directory that this entry refers to.
   ///
-  const DirectoryEntry *getDir() const { return !IsHeaderMap ? u.Dir : 0; }
+  const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; }
+
+  /// getFrameworkDir - Return the directory that this framework refers to.
+  ///
+  const DirectoryEntry *getFrameworkDir() const {
+    return isFramework() ? u.Dir : 0;
+  }
   
   /// getHeaderMap - Return the directory that this entry refers to.
   ///
-  const HeaderMap *getHeaderMap() const { return IsHeaderMap ? u.Map : 0; }
+  const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; }
 
+  LookupType_t getLookupType() const { return (LookupType_t)LookupType; }
+  
   /// isNormalDir - Return true if this is a normal directory, not a header map.
-  bool isNormalDir() const { return !IsHeaderMap; }
+  bool isNormalDir() const { return getLookupType() == LT_NormalDir; }
+  
+  /// isFramework - True if this is a framework directory.
+  ///
+  bool isFramework() const { return getLookupType() == LT_Framework; }
   
   /// isHeaderMap - Return true if this is a header map, not a normal directory.
-  bool isHeaderMap() const { return IsHeaderMap; }
+  bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; }
   
   /// DirCharacteristic - The type of directory this is, one of the DirType enum
   /// values.
@@ -96,9 +116,6 @@
   ///
   bool isUserSupplied() const { return UserSupplied; }
   
-  /// isFramework - True if this is a framework directory.
-  ///
-  bool isFramework() const { return Framework; }
 };
 
 }  // end namespace clang





More information about the cfe-commits mailing list