]> granicus.if.org Git - clang/commitdiff
Step #1 in adding headermap support to clang.
authorChris Lattner <sabre@nondot.org>
Mon, 17 Dec 2007 06:36:45 +0000 (06:36 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 17 Dec 2007 06:36:45 +0000 (06:36 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45089 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/clang.cpp
Lex/HeaderSearch.cpp
clang.xcodeproj/project.pbxproj
include/clang/Lex/DirectoryLookup.h
include/clang/Lex/HeaderMap.h [new file with mode: 0644]
include/clang/Lex/HeaderSearch.h

index 095eaaa6ca0a014cce8240111e897a79e95609e8..4f6ea926d25d0a0e8be5b86bd85f2f14390f57fb 100644 (file)
@@ -613,8 +613,9 @@ static std::vector<DirectoryLookup> IncludeGroup[4];
 ///
 static void AddPath(const std::string &Path, IncludeDirGroup Group,
                     bool isCXXAware, bool isUserSupplied,
-                    bool isFramework, FileManager &FM) {
+                    bool isFramework, HeaderSearch &HS) {
   assert(!Path.empty() && "can't handle empty path here");
+  FileManager &FM = HS.getFileMgr();
   
   // Compute the actual path, taking into consideration -isysroot.
   llvm::SmallString<256> MappedPath;
@@ -648,6 +649,25 @@ static void AddPath(const std::string &Path, IncludeDirGroup Group,
     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;
+    }
+  }
+  
   if (Verbose)
     fprintf(stderr, "ignoring nonexistent directory \"%s\"\n", Path.c_str());
 }
@@ -674,23 +694,23 @@ static void InitializeIncludePaths(HeaderSearch &Headers, FileManager &FM,
                                    const LangOptions &Lang) {
   // Handle -F... options.
   for (unsigned i = 0, e = F_dirs.size(); i != e; ++i)
-    AddPath(F_dirs[i], Angled, false, true, true, FM);
+    AddPath(F_dirs[i], Angled, false, true, true, Headers);
   
   // Handle -I... options.
   for (unsigned i = 0, e = I_dirs.size(); i != e; ++i)
-    AddPath(I_dirs[i], Angled, false, true, false, FM);
+    AddPath(I_dirs[i], Angled, false, true, false, Headers);
   
   // Handle -idirafter... options.
   for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i)
-    AddPath(idirafter_dirs[i], After, false, true, false, FM);
+    AddPath(idirafter_dirs[i], After, false, true, false, Headers);
   
   // Handle -iquote... options.
   for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i)
-    AddPath(iquote_dirs[i], Quoted, false, true, false, FM);
+    AddPath(iquote_dirs[i], Quoted, false, true, false, Headers);
   
   // Handle -isystem... options.
   for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i)
-    AddPath(isystem_dirs[i], System, false, true, false, FM);
+    AddPath(isystem_dirs[i], System, false, true, false, Headers);
 
   // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in
   // parallel, processing the values in order of occurance to get the right
@@ -719,12 +739,12 @@ static void InitializeIncludePaths(HeaderSearch &Headers, FileManager &FM,
                   iwithprefix_vals.getPosition(iwithprefix_idx) < 
                   iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) {
         AddPath(Prefix+iwithprefix_vals[iwithprefix_idx], 
-                System, false, false, false, FM);
+                System, false, false, false, Headers);
         ++iwithprefix_idx;
         iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size();
       } else {
         AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx], 
-                Angled, false, false, false, FM);
+                Angled, false, false, false, Headers);
         ++iwithprefixbefore_idx;
         iwithprefixbefore_done = 
           iwithprefixbefore_idx == iwithprefixbefore_vals.size();
@@ -739,34 +759,35 @@ static void InitializeIncludePaths(HeaderSearch &Headers, FileManager &FM,
   // FIXME: get these from the target?
   if (!nostdinc) {
     if (Lang.CPlusPlus) {
-      AddPath("/usr/include/c++/4.0.0", System, true, false, false, FM);
+      AddPath("/usr/include/c++/4.0.0", System, true, false, false, Headers);
       AddPath("/usr/include/c++/4.0.0/i686-apple-darwin8", System, true, false,
-              false, FM);
-      AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false,FM);
+              false, Headers);
+      AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false,
+              Headers);
     }
     
-    AddPath("/usr/local/include", System, false, false, false, FM);
+    AddPath("/usr/local/include", System, false, false, false, Headers);
     // leopard
     AddPath("/usr/lib/gcc/i686-apple-darwin9/4.0.1/include", System, 
-            false, false, false, FM);
+            false, false, false, Headers);
     AddPath("/usr/lib/gcc/powerpc-apple-darwin9/4.0.1/include", 
-            System, false, false, false, FM);
+            System, false, false, false, Headers);
     AddPath("/usr/lib/gcc/powerpc-apple-darwin9/"
             "4.0.1/../../../../powerpc-apple-darwin0/include", 
-            System, false, false, false, FM);
+            System, false, false, false, Headers);
 
     // tiger
     AddPath("/usr/lib/gcc/i686-apple-darwin8/4.0.1/include", System, 
-            false, false, false, FM);
+            false, false, false, Headers);
     AddPath("/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include", 
-            System, false, false, false, FM);
+            System, false, false, false, Headers);
     AddPath("/usr/lib/gcc/powerpc-apple-darwin8/"
             "4.0.1/../../../../powerpc-apple-darwin8/include", 
-            System, false, false, false, FM);
+            System, false, false, false, Headers);
 
-    AddPath("/usr/include", System, false, false, false, FM);
-    AddPath("/System/Library/Frameworks", System, true, false, true, FM);
-    AddPath("/Library/Frameworks", System, true, false, true, FM);
+    AddPath("/usr/include", System, false, false, false, Headers);
+    AddPath("/System/Library/Frameworks", System, true, false, true, Headers);
+    AddPath("/Library/Frameworks", System, true, false, true, Headers);
   }
 
   // Now that we have collected all of the include paths, merge them all
index 719b9fb9c689c8a72c76dd00ac2bc415b13471ce..c91c4f9ba4e67a8667139271e0ed695721e6cb42 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderMap.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/System/Path.h"
@@ -27,6 +28,12 @@ HeaderSearch::HeaderSearch(FileManager &FM) : FileMgr(FM), FrameworkMap(64) {
   NumFrameworkLookups = NumSubFrameworkLookups = 0;
 }
 
+HeaderSearch::~HeaderSearch() {
+  // Delete headermaps.
+  for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
+    delete HeaderMaps[i].second;
+}
+                           
 void HeaderSearch::PrintStats() {
   fprintf(stderr, "\n*** HeaderSearch Stats:\n");
   fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size());
@@ -49,6 +56,27 @@ void HeaderSearch::PrintStats() {
   fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups);
 }
 
+/// CreateHeaderMap - This method returns a HeaderMap for the specified
+/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
+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 (!HeaderMaps.empty()) {
+    for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
+      if (HeaderMaps[i].first == FE) 
+        return HeaderMaps[i].second;
+  }
+  
+  if (const HeaderMap *HM = HeaderMap::Create(FE, ErrorInfo)) {
+    HeaderMaps.push_back(std::make_pair(FE, HM));
+    return HM;
+  }
+    
+  return 0;
+}
+
+
 //===----------------------------------------------------------------------===//
 // Header File Location.
 //===----------------------------------------------------------------------===//
index 0b2d9fabb035804e1528a43c723234c1b42c3676..649d1fd09e4e0005c85ec4800c21ca036920d994 100644 (file)
                DE6951C60C4D1F5D00A5826B /* RecordLayout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = RecordLayout.h; path = clang/AST/RecordLayout.h; sourceTree = "<group>"; };
                DE6954630C5121BD00A5826B /* Token.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Token.h; sourceTree = "<group>"; };
                DE704B250D0FBEBE009C7762 /* SemaDeclObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDeclObjC.cpp; path = Sema/SemaDeclObjC.cpp; sourceTree = "<group>"; };
+               DE704BD10D1647E7009C7762 /* HeaderMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeaderMap.h; sourceTree = "<group>"; };
                DE75ED280B044DC90020CF81 /* ASTContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTContext.h; path = clang/AST/ASTContext.h; sourceTree = "<group>"; };
                DE75EDF00B06880E0020CF81 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Type.cpp; path = AST/Type.cpp; sourceTree = "<group>"; };
                DE928B120C05659200231DA4 /* ModuleBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleBuilder.cpp; path = CodeGen/ModuleBuilder.cpp; sourceTree = "<group>"; };
                        isa = PBXGroup;
                        children = (
                                DE3450D60AEB543100DBC861 /* DirectoryLookup.h */,
+                               DE704BD10D1647E7009C7762 /* HeaderMap.h */,
                                DE344AB70AE5DF6D00DBC861 /* HeaderSearch.h */,
                                DED7D73B0A524295003AD0FB /* Lexer.h */,
                                1A869A6E0BA2164C008DA07A /* LiteralSupport.h */,
index a1cfb0a340d0a27985a30c93d7251d4c6eab8fad..817c1597bcb0224ef03b6c30182296d48805fd7e 100644 (file)
 
 namespace clang {
 class DirectoryEntry;
+class HeaderMap;
 
-/// DirectoryLookup - This class is used to specify the search order for
-/// directories in #include directives.
+/// 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.
 class DirectoryLookup {
 public:
   enum DirType {
@@ -26,10 +30,16 @@ public:
     SystemHeaderDir,
     ExternCSystemHeaderDir
   };
-private:  
-  /// Dir - This is the actual directory that we're referring to.
-  ///
-  const DirectoryEntry *Dir;
+private:
+  union {  // This union is discriminated by isHeaderMap.
+    /// Dir - This is the actual directory that we're referring to.
+    ///
+    const DirectoryEntry *Dir;
+  
+    /// Map - This is the HeaderMap corresponding if the isHeaderMap field is
+    /// true.
+    const HeaderMap *Map;
+  } u;
   
   /// DirCharacteristic - The type of directory this is, one of the DirType enum
   /// values.
@@ -42,15 +52,35 @@ private:
   /// 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;
 public:
+  /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
+  /// 'dir'.
   DirectoryLookup(const DirectoryEntry *dir, DirType DT, bool isUser,
                   bool isFramework)
-    : Dir(dir), DirCharacteristic(DT), UserSupplied(isUser),
-      Framework(isFramework) {}
+    : DirCharacteristic(DT), UserSupplied(isUser),
+      Framework(isFramework), isHeaderMap(false) {
+    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) {
+    u.Map = map; 
+  }
   
   /// getDir - Return the directory that this entry refers to.
   ///
-  const DirectoryEntry *getDir() const { return Dir; }
+  const DirectoryEntry *getDir() const { return !isHeaderMap ? u.Dir : 0; }
+  
+  /// getHeaderMap - Return the directory that this entry refers to.
+  ///
+  const HeaderMap *getHeaderMap() const { return isHeaderMap ? u.Map : 0; }
   
   /// DirCharacteristic - The type of directory this is, one of the DirType enum
   /// values.
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
new file mode 100644 (file)
index 0000000..7c79fe0
--- /dev/null
@@ -0,0 +1,37 @@
+//===--- HeaderMap.h - A file that acts like dir of symlinks ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the HeaderMap interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERMAP_H
+#define LLVM_CLANG_LEX_HEADERMAP_H
+
+namespace clang {
+
+/// This class represents an Apple concept known as a 'header map'.  To the
+/// #include file resolution process, it basically acts like a directory of
+/// symlinks to files.  Its advantages are that it is dense and more efficient
+/// to create and process than a directory of symlinks.
+class HeaderMap {
+public:
+  /// HeaderMap::Create - This attempts to load the specified file as a header
+  /// map.  If it doesn't look like a HeaderMap, it gives up and returns null.
+  /// If it looks like a HeaderMap but is obviously corrupted, it puts a reason
+  /// into the string error argument and returns null.
+  static const HeaderMap *Create(const FileEntry *FE, std::string &ErrorInfo) { 
+    // FIXME: woot!
+    return 0; 
+  }
+};
+
+} // end namespace clang.
+
+#endif
\ No newline at end of file
index 381c672aebf2025909c477ca0db74c86e0bafbf0..70f7d957ba36458c437f8338262a88475cd1b229 100644 (file)
@@ -81,12 +81,17 @@ class HeaderSearch {
   /// name like "Carbon" to the Carbon.framework directory.
   llvm::StringMap<const DirectoryEntry *> FrameworkMap;
 
+  /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing 
+  /// headermaps.  This vector owns the headermap.
+  std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
+  
   // Various statistics we track for performance analysis.
   unsigned NumIncluded;
   unsigned NumMultiIncludeFileOptzn;
   unsigned NumFrameworkLookups, NumSubFrameworkLookups;
 public:
   HeaderSearch(FileManager &FM);
+  ~HeaderSearch();
 
   FileManager &getFileMgr() const { return FileMgr; }
 
@@ -166,6 +171,10 @@ public:
     getFileInfo(File).ControllingMacro = ControllingMacro;
   }
   
+  /// CreateHeaderMap - This method returns a HeaderMap for the specified
+  /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
+  const HeaderMap *CreateHeaderMap(const FileEntry *FE, std::string &ErrorInfo);
+  
   void PrintStats();
 private:
   const FileEntry *DoFrameworkLookup(const DirectoryEntry *Dir,