diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-07-28 04:45:53 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-07-28 04:45:53 +0000 |
commit | 65e02fa80e1c185f18e5f81cefc30d75383a7301 (patch) | |
tree | 244ea3b8ba968fde89e9bcfe015c8e6ab93ea601 | |
parent | e1adf8177fcd2e571ea2183c20160ab829cb88c8 (diff) |
Introduce the "-index-header-map" option, to give special semantics
for quoted header lookup when dealing with not-yet-installed
frameworks. Fixes <rdar://problem/9824020>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136331 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Driver/CC1Options.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 1 | ||||
-rw-r--r-- | include/clang/Frontend/HeaderSearchOptions.h | 2 | ||||
-rw-r--r-- | include/clang/Lex/DirectoryLookup.h | 20 | ||||
-rw-r--r-- | include/clang/Lex/HeaderSearch.h | 25 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 47 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 6 | ||||
-rw-r--r-- | lib/Lex/HeaderSearch.cpp | 38 | ||||
-rw-r--r-- | test/Driver/index-header-map.c | 4 |
10 files changed, 124 insertions, 24 deletions
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 7eddc01393..1017daeda1 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -609,6 +609,8 @@ def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">, HelpText<"Add directory to include search path">; def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">, HelpText<"Add directory to AFTER include search path">; +def index_header_map : Flag<"-index-header-map">, + HelpText<"Make the next included directory (-I or -F) an indexer header map">; def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">, HelpText<"Add directory to QUOTE include search path">; def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, MetaVarName<"<directory>">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index ff75aa90f3..3ea43c7f6d 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -500,6 +500,7 @@ def gused : Joined<"-gused">, Group<g_Group>; def g_Flag : Flag<"-g">, Group<g_Group>; def g_Joined : Joined<"-g">, Group<g_Group>; def headerpad__max__install__names : Joined<"-headerpad_max_install_names">; +def index_header_map : Flag<"-index-header-map">; def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>; def iframework : JoinedOrSeparate<"-iframework">, Group<clang_i_Group>; def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>; diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index 949dfe1195..e1b1273ff4 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -23,6 +23,8 @@ namespace frontend { enum IncludeDirGroup { Quoted = 0, ///< '#include ""' paths, added by'gcc -iquote'. Angled, ///< Paths for '#include <>' added by '-I'. + IndexHeaderMap, ///< Like Angled, but marks header maps used when + /// building frameworks. System, ///< Like Angled, but marks system directories. CXXSystem, ///< Like System, but only used for C++. After ///< Like System, but searched after the system directories. diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index ca116df9de..ae5eabc690 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -56,21 +56,27 @@ private: /// LookupType - This indicates whether this DirectoryLookup object is a /// normal directory, a framework, or a headermap. unsigned LookupType : 2; + + /// \brief Whether this is a header map used when building a framework. + unsigned IsIndexHeaderMap : 1; + public: /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'dir'. DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT, bool isUser, bool isFramework) - : DirCharacteristic(DT), UserSupplied(isUser), - LookupType(isFramework ? LT_Framework : LT_NormalDir) { + : DirCharacteristic(DT), UserSupplied(isUser), + LookupType(isFramework ? LT_Framework : LT_NormalDir), + IsIndexHeaderMap(false) { u.Dir = dir; } /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'map'. DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT, - bool isUser) - : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap) { + bool isUser, bool isIndexHeaderMap) + : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap), + IsIndexHeaderMap(isIndexHeaderMap) { u.Map = map; } @@ -116,7 +122,11 @@ public: /// bool isUserSupplied() const { return UserSupplied; } - + /// \brief Whether this header map is building a framework or not. + bool isIndexHeaderMap() const { + return isHeaderMap() && IsIndexHeaderMap; + } + /// LookupFile - Lookup the specified file in this search path, returning it /// if it exists or returning null if not. /// diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index b61471d608..676a245305 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -16,6 +16,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" #include <vector> @@ -48,6 +49,15 @@ struct HeaderFileInfo { /// "resolved", meaning that it was loaded from the external source. unsigned Resolved : 1; + /// \brief Whether this is a header inside a framework that is currently + /// being built. + /// + /// When a framework is being built, the headers have not yet been placed + /// into the appropriate framework subdirectories, and therefore are + /// provided via a header map. This bit indicates when this is one of + /// those framework headers. + unsigned IndexHeaderMapHeader : 1; + /// NumIncludes - This is the number of times the file has been included /// already. unsigned short NumIncludes; @@ -69,10 +79,14 @@ struct HeaderFileInfo { /// external storage. const IdentifierInfo *ControllingMacro; + /// \brief If this header came from a framework include, this is the name + /// of the framework. + StringRef Framework; + HeaderFileInfo() : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), - External(false), Resolved(false), NumIncludes(0), ControllingMacroID(0), - ControllingMacro(0) {} + External(false), Resolved(false), IndexHeaderMapHeader(false), + NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {} /// \brief Retrieve the controlling macro for this header file, if /// any. @@ -139,6 +153,10 @@ class HeaderSearch { /// headermaps. This vector owns the headermap. std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps; + /// \brief Uniqued set of framework names, which is used to track which + /// headers were included as framework headers. + llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames; + /// \brief Entity used to resolve the identifier IDs of controlling /// macros into IdentifierInfo pointers, as needed. ExternalIdentifierLookup *ExternalLookup; @@ -325,6 +343,9 @@ public: } search_dir_iterator system_dir_end() const { return SearchDirs.end(); } + /// \brief Retrieve a uniqued framework name. + StringRef getUniqueFrameworkName(StringRef Framework); + void PrintStats(); size_t getTotalMemory() const; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 31413c7cf9..5fd2b9b486 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -341,7 +341,8 @@ void Clang::AddPreprocessingOptions(const Driver &D, } Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U); - Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F); + Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F, + options::OPT_index_header_map); // Add C++ include arguments, if needed. types::ID InputType = Inputs[0].getType(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 8967d5280b..47e9590f47 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -520,17 +520,31 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied)) llvm::report_fatal_error("Invalid option set!"); if (E.IsUserSupplied) { - if (E.Group == frontend::After) { + switch (E.Group) { + case frontend::After: Res.push_back("-idirafter"); - } else if (E.Group == frontend::Quoted) { + break; + + case frontend::Quoted: Res.push_back("-iquote"); - } else if (E.Group == frontend::System) { + break; + + case frontend::System: Res.push_back("-isystem"); - } else if (E.Group == frontend::CXXSystem) { + break; + + case frontend::IndexHeaderMap: + Res.push_back("-index-header-map"); + Res.push_back(E.IsFramework? "-F" : "-I"); + break; + + case frontend::CXXSystem: Res.push_back("-cxx-isystem"); - } else { - assert(E.Group == frontend::Angled && "Invalid group!"); + break; + + case frontend::Angled: Res.push_back(E.IsFramework ? "-F" : "-I"); + break; } } else { if (E.Group != frontend::Angled && E.Group != frontend::System) @@ -1364,11 +1378,24 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.UseLibcxx = (strcmp(A->getValue(Args), "libc++") == 0); Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); - // Add -I... and -F... options in order. - for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F), - ie = Args.filtered_end(); it != ie; ++it) - Opts.AddPath((*it)->getValue(Args), frontend::Angled, true, + // Add -I..., -F..., and -index-header-map options in order. + bool IsIndexHeaderMap = false; + for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F, + OPT_index_header_map), + ie = Args.filtered_end(); it != ie; ++it) { + if ((*it)->getOption().matches(OPT_index_header_map)) { + // -index-header-map applies to the next -I or -F. + IsIndexHeaderMap = true; + continue; + } + + frontend::IncludeDirGroup Group + = IsIndexHeaderMap? frontend::IndexHeaderMap : frontend::Angled; + + Opts.AddPath((*it)->getValue(Args), Group, true, /*IsFramework=*/ (*it)->getOption().matches(OPT_F), false); + IsIndexHeaderMap = false; + } // Add -iprefix/-iwith-prefix/-iwithprefixbefore options. StringRef Prefix = ""; // FIXME: This isn't the correct default prefix. diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index ed763e27c7..f596b992f5 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -134,7 +134,7 @@ void InitHeaderSearch::AddPath(const Twine &Path, // Compute the DirectoryLookup type. SrcMgr::CharacteristicKind Type; - if (Group == Quoted || Group == Angled) + if (Group == Quoted || Group == Angled || Group == IndexHeaderMap) Type = SrcMgr::C_User; else if (isCXXAware) Type = SrcMgr::C_System; @@ -156,7 +156,7 @@ void InitHeaderSearch::AddPath(const Twine &Path, if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) { // It is a headermap, add it to the search path. IncludePath.push_back(std::make_pair(Group, DirectoryLookup(HM, Type, - isUserSupplied))); + isUserSupplied, Group == IndexHeaderMap))); return; } } @@ -1054,7 +1054,7 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) { for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); it != ie; ++it) { - if (it->first == Angled) + if (it->first == Angled || it->first == IndexHeaderMap) SearchList.push_back(it->second); } diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 11cb1ecd8c..2592ada676 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -280,7 +280,23 @@ const FileEntry *HeaderSearch::LookupFile( return FileMgr.getFile(Filename, /*openFile=*/true); } - // Step #0, unless disabled, check to see if the file is in the #includer's + // If we are including a file with a quoted include "foo.h" from inside + // a header in a framework that is currently being built, change the include + // to <Foo/foo.h>, where "Foo" is the name of the framework in which the + // including header was found. + llvm::SmallString<128> ScratchFilename; + if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) { + HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt); + if (IncludingHFI.IndexHeaderMapHeader) { + isAngled = true; + ScratchFilename += IncludingHFI.Framework; + ScratchFilename += '/'; + ScratchFilename += Filename; + Filename = ScratchFilename; + } + } + + // Unless disabled, check to see if the file is in the #includer's // 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". @@ -353,8 +369,20 @@ const FileEntry *HeaderSearch::LookupFile( CurDir = &SearchDirs[i]; // This file is a system header or C++ unfriendly if the dir is. - getFileInfo(FE).DirInfo = CurDir->getDirCharacteristic(); - + HeaderFileInfo &HFI = getFileInfo(FE); + HFI.DirInfo = CurDir->getDirCharacteristic(); + + // If this file is found in a header map and uses the framework style of + // includes, then this header is part of a framework we're building. + if (CurDir->isIndexHeaderMap()) { + size_t SlashPos = Filename.find('/'); + if (SlashPos != StringRef::npos) { + HFI.IndexHeaderMapHeader = 1; + HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), + SlashPos)); + } + } + // Remember this location for the next lookup we do. CacheLookup.second = i; return FE; @@ -550,3 +578,7 @@ size_t HeaderSearch::getTotalMemory() const { + LookupFileCache.getAllocator().getTotalMemory() + FrameworkMap.getAllocator().getTotalMemory(); } + +StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) { + return FrameworkNames.GetOrCreateValue(Framework).getKey(); +} diff --git a/test/Driver/index-header-map.c b/test/Driver/index-header-map.c new file mode 100644 index 0000000000..8bd677a0ba --- /dev/null +++ b/test/Driver/index-header-map.c @@ -0,0 +1,4 @@ +// RUN: %clang -I%S/Before -index-header-map -I%S/Index -I%S/After %s -### 2>> %t.log +// RUN: FileCheck %s < %t.log + +// CHECK: {{-I.*Before.*-index-header-map.*-I.*Index.*-I.*After}} |