diff --git a/clang/Driver/clang.cpp b/clang/Driver/clang.cpp index 089faf125556..c271f5123361 100644 --- a/clang/Driver/clang.cpp +++ b/clang/Driver/clang.cpp @@ -25,6 +25,7 @@ #include "clang.h" #include "ASTConsumers.h" #include "HTMLDiagnostics.h" +#include "clang/Driver/InitHeaderSearch.h" #include "clang/Driver/TextDiagnosticBuffer.h" #include "clang/Driver/TextDiagnosticPrinter.h" #include "clang/Analysis/PathDiagnostic.h" @@ -757,170 +758,43 @@ isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"), llvm::cl::desc("Set the system root directory (usually /)")); // Finally, implement the code that groks the options above. -enum IncludeDirGroup { - Quoted = 0, - Angled, - System, - After -}; - -static std::vector IncludeGroup[4]; - -/// AddPath - Add the specified path to the specified group list. -/// -static void AddPath(const std::string &Path, IncludeDirGroup Group, - bool isCXXAware, bool isUserSupplied, - 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; - - // Handle isysroot. - if (Group == System) { - // FIXME: Portability. This should be a sys::Path interface, this doesn't - // handle things like C:\ right, nor win32 \\network\device\blah. - if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present. - MappedPath.append(isysroot.begin(), isysroot.end()); - } - - MappedPath.append(Path.begin(), Path.end()); - - // Compute the DirectoryLookup type. - DirectoryLookup::DirType Type; - if (Group == Quoted || Group == Angled) - Type = DirectoryLookup::NormalHeaderDir; - else if (isCXXAware) - Type = DirectoryLookup::SystemHeaderDir; - else - Type = DirectoryLookup::ExternCSystemHeaderDir; - - - // If the directory exists, add it. - if (const DirectoryEntry *DE = FM.getDirectory(&MappedPath[0], - &MappedPath[0]+ - MappedPath.size())) { - IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied, - isFramework)); - 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())) { - if (const HeaderMap *HM = HS.CreateHeaderMap(FE)) { - // It is a headermap, add it to the search path. - IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied)); - return; - } - } - } - - if (Verbose) - fprintf(stderr, "ignoring nonexistent directory \"%s\"\n", Path.c_str()); -} - -/// RemoveDuplicates - If there are duplicate directory entries in the specified -/// search list, remove the later (dead) ones. -static void RemoveDuplicates(std::vector &SearchList) { - llvm::SmallPtrSet SeenDirs; - llvm::SmallPtrSet SeenFrameworkDirs; - llvm::SmallPtrSet SeenHeaderMaps; - for (unsigned i = 0; i != SearchList.size(); ++i) { - if (SearchList[i].isNormalDir()) { - // If this isn't the first time we've seen this dir, remove it. - if (SeenDirs.insert(SearchList[i].getDir())) - continue; - - 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. - if (SeenHeaderMaps.insert(SearchList[i].getHeaderMap())) - continue; - - if (Verbose) - fprintf(stderr, "ignoring duplicate directory \"%s\"\n", - SearchList[i].getDir()->getName()); - } - - // This is reached if the current entry is a duplicate. - SearchList.erase(SearchList.begin()+i); - --i; - } -} - -// AddEnvVarPaths - Add a list of paths from an environment variable to a -// header search list. -// -static void AddEnvVarPaths(const char *Name, HeaderSearch &Headers) { - const char* at = getenv(Name); - if (!at) - return; - - const char* delim = strchr(at, llvm::sys::PathSeparator); - while (delim != 0) { - if (delim-at == 0) - AddPath(".", Angled, false, true, false, Headers); - else - AddPath(std::string(at, std::string::size_type(delim-at)), Angled, false, - true, false, Headers); - at = delim + 1; - delim = strchr(at, llvm::sys::PathSeparator); - } - if (*at == 0) - AddPath(".", Angled, false, true, false, Headers); - else - AddPath(at, Angled, false, true, false, Headers); -} /// InitializeIncludePaths - Process the -I options and set them in the /// HeaderSearch object. -static void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers, - FileManager &FM, const LangOptions &Lang) { +void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers, + FileManager &FM, const LangOptions &Lang) { + InitHeaderSearch Init(Headers, Verbose, isysroot); + // Handle -I... and -F... options, walking the lists in parallel. unsigned Iidx = 0, Fidx = 0; while (Iidx < I_dirs.size() && Fidx < F_dirs.size()) { if (I_dirs.getPosition(Iidx) < F_dirs.getPosition(Fidx)) { - AddPath(I_dirs[Iidx], Angled, false, true, false, Headers); + Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false); ++Iidx; } else { - AddPath(F_dirs[Fidx], Angled, false, true, true, Headers); + Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true); ++Fidx; } } // Consume what's left from whatever list was longer. for (; Iidx != I_dirs.size(); ++Iidx) - AddPath(I_dirs[Iidx], Angled, false, true, false, Headers); + Init.AddPath(I_dirs[Iidx], InitHeaderSearch::Angled, false, true, false); for (; Fidx != F_dirs.size(); ++Fidx) - AddPath(F_dirs[Fidx], Angled, false, true, true, Headers); + Init.AddPath(F_dirs[Fidx], InitHeaderSearch::Angled, false, true, true); // Handle -idirafter... options. for (unsigned i = 0, e = idirafter_dirs.size(); i != e; ++i) - AddPath(idirafter_dirs[i], After, false, true, false, Headers); + Init.AddPath(idirafter_dirs[i], InitHeaderSearch::After, + false, true, false); // Handle -iquote... options. for (unsigned i = 0, e = iquote_dirs.size(); i != e; ++i) - AddPath(iquote_dirs[i], Quoted, false, true, false, Headers); + Init.AddPath(iquote_dirs[i], InitHeaderSearch::Quoted, false, true, false); // Handle -isystem... options. for (unsigned i = 0, e = isystem_dirs.size(); i != e; ++i) - AddPath(isystem_dirs[i], System, false, true, false, Headers); + Init.AddPath(isystem_dirs[i], InitHeaderSearch::System, false, true, false); // Walk the -iprefix/-iwithprefix/-iwithprefixbefore argument lists in // parallel, processing the values in order of occurance to get the right @@ -948,13 +822,13 @@ static void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers, (iwithprefixbefore_done || iwithprefix_vals.getPosition(iwithprefix_idx) < iwithprefixbefore_vals.getPosition(iwithprefixbefore_idx))) { - AddPath(Prefix+iwithprefix_vals[iwithprefix_idx], - System, false, false, false, Headers); + Init.AddPath(Prefix+iwithprefix_vals[iwithprefix_idx], + InitHeaderSearch::System, false, false, false); ++iwithprefix_idx; iwithprefix_done = iwithprefix_idx == iwithprefix_vals.size(); } else { - AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx], - Angled, false, false, false, Headers); + Init.AddPath(Prefix+iwithprefixbefore_vals[iwithprefixbefore_idx], + InitHeaderSearch::Angled, false, false, false); ++iwithprefixbefore_idx; iwithprefixbefore_done = iwithprefixbefore_idx == iwithprefixbefore_vals.size(); @@ -962,15 +836,7 @@ static void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers, } } - AddEnvVarPaths("CPATH", Headers); - if (Lang.CPlusPlus && Lang.ObjC1) - AddEnvVarPaths("OBJCPLUS_INCLUDE_PATH", Headers); - else if (Lang.CPlusPlus) - AddEnvVarPaths("CPLUS_INCLUDE_PATH", Headers); - else if (Lang.ObjC1) - AddEnvVarPaths("OBJC_INCLUDE_PATH", Headers); - else - AddEnvVarPaths("C_INCLUDE_PATH", Headers); + Init.AddDefaultEnvVarPaths(Lang); // Add the clang headers, which are relative to the clang driver. llvm::sys::Path MainExecutablePath = @@ -980,167 +846,17 @@ static void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers, MainExecutablePath.eraseComponent(); // Remove /clang from foo/bin/clang MainExecutablePath.eraseComponent(); // Remove /bin from foo/bin MainExecutablePath.appendComponent("Headers"); // Get foo/Headers - AddPath(MainExecutablePath.c_str(), System, false, false, false, Headers); + Init.AddPath(MainExecutablePath.c_str(), InitHeaderSearch::System, + false, false, false); } - // FIXME: temporary hack: hard-coded paths. - // FIXME: get these from the target? - if (!nostdinc) { - if (Lang.CPlusPlus) { - AddPath("/usr/include/c++/4.2.1", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.2.1/i686-apple-darwin10", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.2.1/backward", System, true, false, false, - Headers); - - 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, Headers); - AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false, - Headers); - - // Ubuntu 7.10 - Gutsy Gibbon - AddPath("/usr/include/c++/4.1.3", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.1.3/i486-linux-gnu", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false, - Headers); - - // Fedora 8 - AddPath("/usr/include/c++/4.1.2", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.1.2/backward", System, true, false, false, - Headers); - - // Fedora 9 - AddPath("/usr/include/c++/4.3.0", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.3.0/i386-redhat-linux", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.3.0/backward", System, true, false, false, - Headers); - - // Arch Linux 2008-06-24 - AddPath("/usr/include/c++/4.3.1", System, true, false, false, Headers); - AddPath("/usr/include/c++/4.3.1/i686-pc-linux-gnu", System, true, false, - false, Headers); - AddPath("/usr/include/c++/4.3.1/backward", System, true, false, false, - Headers); - AddPath("/usr/include/c++/4.3.1/x86_64-unknown-linux-gnu", System, true, - false, false, Headers); - } - - AddPath("/usr/local/include", System, false, false, false, Headers); - - AddPath("/usr/lib/gcc/i686-apple-darwin10/4.2.1/include", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/include", - System, false, false, false, Headers); - - // leopard - AddPath("/usr/lib/gcc/i686-apple-darwin9/4.0.1/include", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin9/4.0.1/include", - System, false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin9/" - "4.0.1/../../../../powerpc-apple-darwin0/include", - System, false, false, false, Headers); - - // tiger - AddPath("/usr/lib/gcc/i686-apple-darwin8/4.0.1/include", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include", - System, false, false, false, Headers); - AddPath("/usr/lib/gcc/powerpc-apple-darwin8/" - "4.0.1/../../../../powerpc-apple-darwin8/include", - System, false, false, false, Headers); - - // Ubuntu 7.10 - Gutsy Gibbon - AddPath("/usr/lib/gcc/i486-linux-gnu/4.1.3/include", System, - false, false, false, Headers); - - // Fedora 8 - AddPath("/usr/lib/gcc/i386-redhat-linux/4.1.2/include", System, - false, false, false, Headers); - - // Fedora 9 - AddPath("/usr/lib/gcc/i386-redhat-linux/4.3.0/include", System, - false, false, false, Headers); - - //Debian testing/lenny x86 - AddPath("/usr/lib/gcc/i486-linux-gnu/4.2.3/include", System, - false, false, false, Headers); - - //Debian testing/lenny amd64 - AddPath("/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include", System, - false, false, false, Headers); - - // Arch Linux 2008-06-24 - AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.3.1/include", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.3.1/include-fixed", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include", System, - false, false, false, Headers); - AddPath("/usr/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include-fixed", - System, false, false, false, Headers); - - // Debian testing/lenny ppc32 - AddPath("/usr/lib/gcc/powerpc-linux-gnu/4.2.3/include", System, - false, false, false, Headers); - - // Gentoo x86 stable - AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include", System, - false, false, false, Headers); - - 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); - } + if (!nostdinc) + Init.AddDefaultSystemIncludePaths(Lang); // Now that we have collected all of the include paths, merge them all // together and tell the preprocessor about them. - // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList. - std::vector SearchList; - SearchList = IncludeGroup[Angled]; - SearchList.insert(SearchList.end(), IncludeGroup[System].begin(), - IncludeGroup[System].end()); - SearchList.insert(SearchList.end(), IncludeGroup[After].begin(), - IncludeGroup[After].end()); - RemoveDuplicates(SearchList); - RemoveDuplicates(IncludeGroup[Quoted]); - - // Prepend QUOTED list on the search list. - SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(), - IncludeGroup[Quoted].end()); - - - bool DontSearchCurDir = false; // TODO: set to true if -I- is set? - Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(), - DontSearchCurDir); - - // If verbose, print the list of directories that will be searched. - if (Verbose) { - fprintf(stderr, "#include \"...\" search starts here:\n"); - unsigned QuotedIdx = IncludeGroup[Quoted].size(); - for (unsigned i = 0, e = SearchList.size(); i != e; ++i) { - if (i == QuotedIdx) - fprintf(stderr, "#include <...> search starts here:\n"); - const char *Name = SearchList[i].getName(); - const char *Suffix; - if (SearchList[i].isNormalDir()) - Suffix = ""; - else if (SearchList[i].isFramework()) - Suffix = " (framework directory)"; - else { - assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup"); - Suffix = " (headermap)"; - } - fprintf(stderr, " %s%s\n", Name, Suffix); - } - fprintf(stderr, "End of search list.\n"); - } + Init.Realize(); } //===----------------------------------------------------------------------===// @@ -1491,11 +1207,6 @@ int main(int argc, char **argv) { // Process the -I options and set them in the HeaderInfo. HeaderSearch HeaderInfo(FileMgr); - // FIXME: Sink IncludeGroup into this loop. - IncludeGroup[0].clear(); - IncludeGroup[1].clear(); - IncludeGroup[2].clear(); - IncludeGroup[3].clear(); InitializeIncludePaths(argv[0], HeaderInfo, FileMgr, LangInfo); // Set up the preprocessor with these options. diff --git a/clang/include/clang/Driver/InitHeaderSearch.h b/clang/include/clang/Driver/InitHeaderSearch.h new file mode 100644 index 000000000000..a113456e8a5b --- /dev/null +++ b/clang/include/clang/Driver/InitHeaderSearch.h @@ -0,0 +1,74 @@ +//===--- InitHeaderSearch.h - Initialize header search paths ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the InitHeaderSearch class. +// +//===----------------------------------------------------------------------===// + +#ifndef DRIVER_INIT_HEADER_SEARCH_H_ +#define DRIVER_INIT_HEADER_SEARCH_H_ + +#include +#include + +#include "clang/Lex/DirectoryLookup.h" + +namespace clang { + +class HeaderSearch; +class LangOptions; + +/// InitHeaderSearch - This class makes it easier to set the search paths of +/// a HeaderSearch object. InitHeaderSearch stores several search path lists +/// internally, which can be sent to a HeaderSearch object in one swoop. +class InitHeaderSearch { + std::vector IncludeGroup[4]; + HeaderSearch& Headers; + bool Verbose; + std::string isysroot; + +public: + /// InitHeaderSearch::IncludeDirGroup - Identifies the several search path + /// lists stored internally. + enum IncludeDirGroup { + Quoted = 0, //< `#include ""` paths. Thing `gcc -iquote`. + Angled, //< Paths for both `#include ""` and `#include <>`. (`-I`) + System, //< Like Angled, but marks system directories. + After //< Like System, but searched after the system directories. + }; + + InitHeaderSearch(HeaderSearch &HS, + bool verbose = false, const std::string &iSysroot = "") + : Headers(HS), Verbose(verbose), isysroot(iSysroot) {} + + /// AddPath - Add the specified path to the specified group list. + void AddPath(const std::string &Path, IncludeDirGroup Group, + bool isCXXAware, bool isUserSupplied, + bool isFramework); + + /// AddEnvVarPaths - Add a list of paths from an environment variable to a + /// header search list. + void AddEnvVarPaths(const char *Name); + + /// AddDefaultEnvVarPaths - Adds list of paths from default environment + /// variables such as CPATH. + void AddDefaultEnvVarPaths(const LangOptions &Lang); + + /// AddDefaultSystemIncludePaths - Adds the default system include paths so + /// that e.g. stdio.h is found. + void AddDefaultSystemIncludePaths(const LangOptions &Lang); + + /// Realise - Merges all search path lists into one list and send it to + /// HeaderSearch. + void Realize(); +}; + +} // end namespace clang + +#endif diff --git a/clang/lib/Driver/InitHeaderSearch.cpp b/clang/lib/Driver/InitHeaderSearch.cpp new file mode 100644 index 000000000000..7fd36f80e97f --- /dev/null +++ b/clang/lib/Driver/InitHeaderSearch.cpp @@ -0,0 +1,312 @@ +//===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the InitHeaderSearch class. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/InitHeaderSearch.h" + +#include "clang/Lex/HeaderSearch.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/System/Path.h" + +#include + +using namespace clang; + +void InitHeaderSearch::AddPath(const std::string &Path, IncludeDirGroup Group, + bool isCXXAware, bool isUserSupplied, + bool isFramework) { + assert(!Path.empty() && "can't handle empty path here"); + FileManager &FM = Headers.getFileMgr(); + + // Compute the actual path, taking into consideration -isysroot. + llvm::SmallString<256> MappedPath; + + // Handle isysroot. + if (Group == System) { + // FIXME: Portability. This should be a sys::Path interface, this doesn't + // handle things like C:\ right, nor win32 \\network\device\blah. + if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present. + MappedPath.append(isysroot.begin(), isysroot.end()); + } + + MappedPath.append(Path.begin(), Path.end()); + + // Compute the DirectoryLookup type. + DirectoryLookup::DirType Type; + if (Group == Quoted || Group == Angled) + Type = DirectoryLookup::NormalHeaderDir; + else if (isCXXAware) + Type = DirectoryLookup::SystemHeaderDir; + else + Type = DirectoryLookup::ExternCSystemHeaderDir; + + + // If the directory exists, add it. + if (const DirectoryEntry *DE = FM.getDirectory(&MappedPath[0], + &MappedPath[0]+ + MappedPath.size())) { + IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied, + isFramework)); + 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())) { + if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) { + // It is a headermap, add it to the search path. + IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied)); + return; + } + } + } + + if (Verbose) + fprintf(stderr, "ignoring nonexistent directory \"%s\"\n", Path.c_str()); +} + + +void InitHeaderSearch::AddEnvVarPaths(const char *Name) { + const char* at = getenv(Name); + if (!at) + return; + + const char* delim = strchr(at, llvm::sys::PathSeparator); + while (delim != 0) { + if (delim-at == 0) + AddPath(".", Angled, false, true, false); + else + AddPath(std::string(at, std::string::size_type(delim-at)), Angled, false, + true, false); + at = delim + 1; + delim = strchr(at, llvm::sys::PathSeparator); + } + if (*at == 0) + AddPath(".", Angled, false, true, false); + else + AddPath(at, Angled, false, true, false); +} + + +void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang) { + // FIXME: temporary hack: hard-coded paths. + // FIXME: get these from the target? + if (Lang.CPlusPlus) { + AddPath("/usr/include/c++/4.2.1", System, true, false, false); + AddPath("/usr/include/c++/4.2.1/i686-apple-darwin10", System, true, false, + false); + AddPath("/usr/include/c++/4.2.1/backward", System, true, false, false); + + AddPath("/usr/include/c++/4.0.0", System, true, false, false); + AddPath("/usr/include/c++/4.0.0/i686-apple-darwin8", System, true, false, + false); + AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false); + + // Ubuntu 7.10 - Gutsy Gibbon + AddPath("/usr/include/c++/4.1.3", System, true, false, false); + AddPath("/usr/include/c++/4.1.3/i486-linux-gnu", System, true, false, + false); + AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false); + + // Fedora 8 + AddPath("/usr/include/c++/4.1.2", System, true, false, false); + AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false, + false); + AddPath("/usr/include/c++/4.1.2/backward", System, true, false, false); + + // Fedora 9 + AddPath("/usr/include/c++/4.3.0", System, true, false, false); + AddPath("/usr/include/c++/4.3.0/i386-redhat-linux", System, true, false, + false); + AddPath("/usr/include/c++/4.3.0/backward", System, true, false, false); + + // Arch Linux 2008-06-24 + AddPath("/usr/include/c++/4.3.1", System, true, false, false); + AddPath("/usr/include/c++/4.3.1/i686-pc-linux-gnu", System, true, false, + false); + AddPath("/usr/include/c++/4.3.1/backward", System, true, false, false); + AddPath("/usr/include/c++/4.3.1/x86_64-unknown-linux-gnu", System, true, + false, false); + } + + AddPath("/usr/local/include", System, false, false, false); + + AddPath("/usr/lib/gcc/i686-apple-darwin10/4.2.1/include", System, + false, false, false); + AddPath("/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/include", + System, false, false, false); + + // leopard + AddPath("/usr/lib/gcc/i686-apple-darwin9/4.0.1/include", System, + false, false, false); + AddPath("/usr/lib/gcc/powerpc-apple-darwin9/4.0.1/include", + System, false, false, false); + AddPath("/usr/lib/gcc/powerpc-apple-darwin9/" + "4.0.1/../../../../powerpc-apple-darwin0/include", + System, false, false, false); + + // tiger + AddPath("/usr/lib/gcc/i686-apple-darwin8/4.0.1/include", System, + false, false, false); + AddPath("/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include", + System, false, false, false); + AddPath("/usr/lib/gcc/powerpc-apple-darwin8/" + "4.0.1/../../../../powerpc-apple-darwin8/include", + System, false, false, false); + + // Ubuntu 7.10 - Gutsy Gibbon + AddPath("/usr/lib/gcc/i486-linux-gnu/4.1.3/include", System, + false, false, false); + + // Fedora 8 + AddPath("/usr/lib/gcc/i386-redhat-linux/4.1.2/include", System, + false, false, false); + + // Fedora 9 + AddPath("/usr/lib/gcc/i386-redhat-linux/4.3.0/include", System, + false, false, false); + + //Debian testing/lenny x86 + AddPath("/usr/lib/gcc/i486-linux-gnu/4.2.3/include", System, + false, false, false); + + //Debian testing/lenny amd64 + AddPath("/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include", System, + false, false, false); + + // Arch Linux 2008-06-24 + AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.3.1/include", System, + false, false, false); + AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.3.1/include-fixed", System, + false, false, false); + AddPath("/usr/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include", System, + false, false, false); + AddPath("/usr/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include-fixed", + System, false, false, false); + + // Debian testing/lenny ppc32 + AddPath("/usr/lib/gcc/powerpc-linux-gnu/4.2.3/include", System, + false, false, false); + + // Gentoo x86 stable + AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include", System, + false, false, false); + + AddPath("/usr/include", System, false, false, false); + AddPath("/System/Library/Frameworks", System, true, false, true); + AddPath("/Library/Frameworks", System, true, false, true); +} + +void InitHeaderSearch::AddDefaultEnvVarPaths(const LangOptions &Lang) { + AddEnvVarPaths("CPATH"); + if (Lang.CPlusPlus && Lang.ObjC1) + AddEnvVarPaths("OBJCPLUS_INCLUDE_PATH"); + else if (Lang.CPlusPlus) + AddEnvVarPaths("CPLUS_INCLUDE_PATH"); + else if (Lang.ObjC1) + AddEnvVarPaths("OBJC_INCLUDE_PATH"); + else + AddEnvVarPaths("C_INCLUDE_PATH"); +} + + +/// RemoveDuplicates - If there are duplicate directory entries in the specified +/// search list, remove the later (dead) ones. +static void RemoveDuplicates(std::vector &SearchList, + bool Verbose) { + llvm::SmallPtrSet SeenDirs; + llvm::SmallPtrSet SeenFrameworkDirs; + llvm::SmallPtrSet SeenHeaderMaps; + for (unsigned i = 0; i != SearchList.size(); ++i) { + if (SearchList[i].isNormalDir()) { + // If this isn't the first time we've seen this dir, remove it. + if (SeenDirs.insert(SearchList[i].getDir())) + continue; + + 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. + if (SeenHeaderMaps.insert(SearchList[i].getHeaderMap())) + continue; + + if (Verbose) + fprintf(stderr, "ignoring duplicate directory \"%s\"\n", + SearchList[i].getDir()->getName()); + } + + // This is reached if the current entry is a duplicate. + SearchList.erase(SearchList.begin()+i); + --i; + } +} + + +void InitHeaderSearch::Realize() { + // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList. + std::vector SearchList; + SearchList = IncludeGroup[Angled]; + SearchList.insert(SearchList.end(), IncludeGroup[System].begin(), + IncludeGroup[System].end()); + SearchList.insert(SearchList.end(), IncludeGroup[After].begin(), + IncludeGroup[After].end()); + RemoveDuplicates(SearchList, Verbose); + RemoveDuplicates(IncludeGroup[Quoted], Verbose); + + // Prepend QUOTED list on the search list. + SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(), + IncludeGroup[Quoted].end()); + + + bool DontSearchCurDir = false; // TODO: set to true if -I- is set? + Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(), + DontSearchCurDir); + + // If verbose, print the list of directories that will be searched. + if (Verbose) { + fprintf(stderr, "#include \"...\" search starts here:\n"); + unsigned QuotedIdx = IncludeGroup[Quoted].size(); + for (unsigned i = 0, e = SearchList.size(); i != e; ++i) { + if (i == QuotedIdx) + fprintf(stderr, "#include <...> search starts here:\n"); + const char *Name = SearchList[i].getName(); + const char *Suffix; + if (SearchList[i].isNormalDir()) + Suffix = ""; + else if (SearchList[i].isFramework()) + Suffix = " (framework directory)"; + else { + assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup"); + Suffix = " (headermap)"; + } + fprintf(stderr, " %s%s\n", Name, Suffix); + } + fprintf(stderr, "End of search list.\n"); + } +} +