Add support for CPATH and friends.

This moves the existing code for CPATH into the driver and adds the environment lookup and path splitting there.
The paths are then passed down to cc1 with -I options (CPATH), added after the normal user-specified include dirs.
Language specific paths are passed via -LANG-isystem and the actual filtering is performed in the frontend.

I tried to match GCC's behavior as close as possible

Fixes PR8971.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140341 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2011-09-22 21:41:16 +00:00
Родитель 4cd06348a8
Коммит 47adebef0d
6 изменённых файлов: 115 добавлений и 75 удалений

Просмотреть файл

@ -623,8 +623,16 @@ 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 c_isystem : JoinedOrSeparate<"-c-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to the C SYSTEM include search path">;
def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to the C++ SYSTEM include search path">;
def objc_isystem : JoinedOrSeparate<"-objc-isystem">,
MetaVarName<"<directory>">,
HelpText<"Add directory to the ObjC SYSTEM include search path">;
def objcxx_isystem : JoinedOrSeparate<"-objcxx-isystem">,
MetaVarName<"<directory>">,
HelpText<"Add directory to the ObjC++ SYSTEM include search path">;
def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to SYSTEM include search path">;
def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,

Просмотреть файл

@ -26,7 +26,10 @@ namespace frontend {
IndexHeaderMap, ///< Like Angled, but marks header maps used when
/// building frameworks.
System, ///< Like Angled, but marks system directories.
CSystem, ///< Like System, but only used for C.
CXXSystem, ///< Like System, but only used for C++.
ObjCSystem, ///< Like System, but only used for ObjC.
ObjCXXSystem, ///< Like System, but only used for ObjC++.
After ///< Like System, but searched after the system directories.
};
}
@ -59,18 +62,6 @@ public:
/// User specified include entries.
std::vector<Entry> UserEntries;
/// A (system-path) delimited list of include paths to be added from the
/// environment following the user specified includes (but prior to builtin
/// and standard includes). This is parsed in the same manner as the CPATH
/// environment variable for gcc.
std::string EnvIncPath;
/// Per-language environmental include paths, see \see EnvIncPath.
std::string CEnvIncPath;
std::string ObjCEnvIncPath;
std::string CXXEnvIncPath;
std::string ObjCXXEnvIncPath;
/// The directory which holds the compiler resource files (builtin includes,
/// etc.).
std::string ResourceDir;

Просмотреть файл

@ -183,6 +183,38 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(ProfileRT));
}
static void AddIncludeDirectoryList(const ArgList &Args,
ArgStringList &CmdArgs,
const char *ArgName,
const char *DirList) {
if (!DirList)
return; // Nothing to do.
StringRef Dirs(DirList);
if (Dirs.empty()) // Empty string should not add '.'.
return;
StringRef::size_type Delim;
while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) {
if (Delim == 0) { // Leading colon.
CmdArgs.push_back(ArgName);
CmdArgs.push_back(".");
} else {
CmdArgs.push_back(ArgName);
CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
}
Dirs = Dirs.substr(Delim + 1);
}
if (Dirs.empty()) { // Trailing colon.
CmdArgs.push_back(ArgName);
CmdArgs.push_back(".");
} else { // Add the last path.
CmdArgs.push_back(ArgName);
CmdArgs.push_back(Args.MakeArgString(Dirs));
}
}
void Clang::AddPreprocessingOptions(const Driver &D,
const ArgList &Args,
ArgStringList &CmdArgs,
@ -391,6 +423,23 @@ void Clang::AddPreprocessingOptions(const Driver &D,
}
Args.AddAllArgs(CmdArgs, options::OPT_fauto_module_import);
// Parse additional include paths from environment variables.
// CPATH - included following the user specified includes (but prior to
// builtin and standard includes).
AddIncludeDirectoryList(Args, CmdArgs, "-I", ::getenv("CPATH"));
// C_INCLUDE_PATH - system includes enabled when compiling C.
AddIncludeDirectoryList(Args, CmdArgs, "-c-isystem",
::getenv("C_INCLUDE_PATH"));
// CPLUS_INCLUDE_PATH - system includes enabled when compiling C++.
AddIncludeDirectoryList(Args, CmdArgs, "-cxx-isystem",
::getenv("CPLUS_INCLUDE_PATH"));
// OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC.
AddIncludeDirectoryList(Args, CmdArgs, "-objc-isystem",
::getenv("OBJC_INCLUDE_PATH"));
// OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++.
AddIncludeDirectoryList(Args, CmdArgs, "-objcxx-isystem",
::getenv("OBJCPLUS_INCLUDE_PATH"));
}
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.

Просмотреть файл

@ -534,9 +534,21 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
Res.push_back(E.IsFramework? "-F" : "-I");
break;
case frontend::CSystem:
Res.push_back("-c-isystem");
break;
case frontend::CXXSystem:
Res.push_back("-cxx-isystem");
break;
case frontend::ObjCSystem:
Res.push_back("-objc-isystem");
break;
case frontend::ObjCXXSystem:
Res.push_back("-objcxx-isystem");
break;
case frontend::Angled:
Res.push_back(E.IsFramework ? "-F" : "-I");
@ -551,26 +563,6 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
Res.push_back(E.Path);
}
if (!Opts.EnvIncPath.empty()) {
// FIXME: Provide an option for this, and move env detection to driver.
llvm::report_fatal_error("Not yet implemented!");
}
if (!Opts.CEnvIncPath.empty()) {
// FIXME: Provide an option for this, and move env detection to driver.
llvm::report_fatal_error("Not yet implemented!");
}
if (!Opts.ObjCEnvIncPath.empty()) {
// FIXME: Provide an option for this, and move env detection to driver.
llvm::report_fatal_error("Not yet implemented!");
}
if (!Opts.CXXEnvIncPath.empty()) {
// FIXME: Provide an option for this, and move env detection to driver.
llvm::report_fatal_error("Not yet implemented!");
}
if (!Opts.ObjCXXEnvIncPath.empty()) {
// FIXME: Provide an option for this, and move env detection to driver.
llvm::report_fatal_error("Not yet implemented!");
}
if (!Opts.ResourceDir.empty()) {
Res.push_back("-resource-dir");
Res.push_back(Opts.ResourceDir);
@ -1424,14 +1416,25 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
for (arg_iterator it = Args.filtered_begin(OPT_iquote),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, false);
for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem, OPT_isystem,
for (arg_iterator it = Args.filtered_begin(OPT_isystem,
OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args),
((*it)->getOption().matches(OPT_cxx_isystem) ?
frontend::CXXSystem : frontend::System),
true, false, !(*it)->getOption().matches(OPT_iwithsysroot));
// FIXME: Need options for the various environment variables!
Opts.AddPath((*it)->getValue(Args), frontend::System, true, false,
!(*it)->getOption().matches(OPT_iwithsysroot));
// Add the paths for the various language specific isystem flags.
for (arg_iterator it = Args.filtered_begin(OPT_c_isystem),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::CSystem, true, false, true);
for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::CXXSystem, true, false, true);
for (arg_iterator it = Args.filtered_begin(OPT_objc_isystem),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::ObjCSystem, true, false,true);
for (arg_iterator it = Args.filtered_begin(OPT_objcxx_isystem),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::ObjCXXSystem, true, false,
true);
}
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,

Просмотреть файл

@ -81,10 +81,6 @@ public:
void AddMinGW64CXXPaths(StringRef Base,
StringRef Version);
/// AddDelimitedPaths - Add a list of paths delimited by the system PATH
/// separator. The processing follows that of the CPATH variable for gcc.
void AddDelimitedPaths(StringRef String);
// AddDefaultCIncludePaths - Add paths that should always be searched.
void AddDefaultCIncludePaths(const llvm::Triple &triple,
const HeaderSearchOptions &HSOpts);
@ -167,26 +163,6 @@ void InitHeaderSearch::AddPath(const Twine &Path,
<< MappedPathStr << "\"\n";
}
void InitHeaderSearch::AddDelimitedPaths(StringRef at) {
if (at.empty()) // Empty string should not add '.' path.
return;
StringRef::size_type delim;
while ((delim = at.find(llvm::sys::PathSeparator)) != StringRef::npos) {
if (delim == 0)
AddPath(".", Angled, false, true, false);
else
AddPath(at.substr(0, delim), Angled, false, true, false);
at = at.substr(delim + 1);
}
if (at.empty())
AddPath(".", Angled, false, true, false);
else
AddPath(at, Angled, false, true, false);
}
void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base,
StringRef ArchDir,
StringRef Dir32,
@ -1094,7 +1070,11 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
it != ie; ++it) {
if (it->first == System || (Lang.CPlusPlus && it->first == CXXSystem))
if (it->first == System ||
(!Lang.ObjC1 && !Lang.CPlusPlus && it->first == CSystem) ||
(!Lang.ObjC1 && Lang.CPlusPlus && it->first == CXXSystem) ||
(Lang.ObjC1 && !Lang.CPlusPlus && it->first == ObjCSystem) ||
(Lang.ObjC1 && Lang.CPlusPlus && it->first == ObjCXXSystem))
SearchList.push_back(it->second);
}
@ -1147,17 +1127,6 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
E.IgnoreSysRoot);
}
// Add entries from CPATH and friends.
Init.AddDelimitedPaths(HSOpts.EnvIncPath);
if (Lang.CPlusPlus && Lang.ObjC1)
Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath);
else if (Lang.CPlusPlus)
Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath);
else if (Lang.ObjC1)
Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath);
else
Init.AddDelimitedPaths(HSOpts.CEnvIncPath);
if (HSOpts.UseStandardIncludes)
Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts);

20
test/Driver/cpath.c Normal file
Просмотреть файл

@ -0,0 +1,20 @@
// RUN: mkdir -p %T/test1 %T/test2
// RUN: CPATH=%T/test1: %clang -x c -E -v %s 2>&1 | FileCheck %s -check-prefix=CPATH
// CPATH: -I {{.*}}/test1 -I .
// CPATH: search starts here
// CPATH: test1
// RUN: OBJC_INCLUDE_PATH=%T/test1 OBJCPLUS_INCLUDE_PATH=%T/test1 CPLUS_INCLUDE_PATH=%T/test1 C_INCLUDE_PATH=%T/test2 %clang -x c -E -v %s 2>&1 | FileCheck %s -check-prefix=C_INCLUDE_PATH
// C_INCLUDE_PATH: -c-isystem {{.*}}/test2 -cxx-isystem {{.*}}/test1 -objc-isystem {{.*}}/test1 -objcxx-isystem {{.*}}/test1
// C_INCLUDE_PATH: search starts here
// C_INCLUDE_PATH-NOT: test1
// C_INCLUDE_PATH: test2
// C_INCLUDE_PATH-NOT: test1
// RUN: OBJC_INCLUDE_PATH=%T/test1 OBJCPLUS_INCLUDE_PATH=%T/test2 CPLUS_INCLUDE_PATH=%T/test1 C_INCLUDE_PATH=%T/test1 %clang -x objective-c++ -E -v %s 2>&1 | FileCheck %s -check-prefix=OBJCPLUS_INCLUDE_PATH
// OBJCPLUS_INCLUDE_PATH: -c-isystem {{.*}}/test1 -cxx-isystem {{.*}}/test1 -objc-isystem {{.*}}/test1 -objcxx-isystem {{.*}}/test2
// OBJCPLUS_INCLUDE_PATH: search starts here
// OBJCPLUS_INCLUDE_PATH-NOT: test1
// OBJCPLUS_INCLUDE_PATH: test2
// OBJCPLUS_INCLUDE_PATH-NOT: test1