]> granicus.if.org Git - clang/commitdiff
Add support for CPATH and friends.
authorBenjamin Kramer <benny.kra@googlemail.com>
Thu, 22 Sep 2011 21:41:16 +0000 (21:41 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Thu, 22 Sep 2011 21:41:16 +0000 (21:41 +0000)
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

include/clang/Driver/CC1Options.td
include/clang/Frontend/HeaderSearchOptions.h
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/InitHeaderSearch.cpp
test/Driver/cpath.c [new file with mode: 0644]

index ba9469a949495718b001d11b1196298e72e06029..ad61f6a9f4928cb753e56e3447c070a1f960afdd 100644 (file)
@@ -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>">,
index e0f80e3bdf3f67a72d07de81386daa4292fdb5b5..39d31363745a0b8eff13fec57ae6387b0ddf04f3 100644 (file)
@@ -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;
index 840e4c273486191872e6488889311bb654655d0e..c3c07f412f803a2ca88440cd6d3c270201dc92ae 100644 (file)
@@ -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.
index 7cb707b966179351cf2a99a37b65b0f882b26ecd..e69926137918a881428e786861bad859a0f9229d 100644 (file)
@@ -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,
index 08af53226754f4caca4e77df2b4c61f8b46ca270..089ded19cef9cff4f835cb24867443f883bcaa32 100644 (file)
@@ -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);
 
diff --git a/test/Driver/cpath.c b/test/Driver/cpath.c
new file mode 100644 (file)
index 0000000..00ed879
--- /dev/null
@@ -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