]> granicus.if.org Git - clang/commitdiff
Extend linux header search to find libc++ headers in c++/vN for any N.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Mon, 9 Nov 2015 21:10:54 +0000 (21:10 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Mon, 9 Nov 2015 21:10:54 +0000 (21:10 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@252514 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Driver/ToolChains.cpp
test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/bin/.keep [new file with mode: 0644]
test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/include/c++/v1/.keep [new file with mode: 0644]
test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/include/c++/v2/.keep [new file with mode: 0644]
test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/lib/.keep [new file with mode: 0644]
test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/bin/.keep [new file with mode: 0644]
test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/4.8/backward/.keep [new file with mode: 0755]
test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/v1/.keep [new file with mode: 0644]
test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/v2/.keep [new file with mode: 0644]
test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/lib/.keep [new file with mode: 0644]
test/Driver/linux-header-search.cpp

index d39bfaa4bec13cb50fa3bcece00d80e35070c2bd..5df96ce54e3f52092b8c2dc08a1376c252ba3dea 100644 (file)
@@ -3849,6 +3849,25 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 }
 
 
+static std::string DetectLibcxxIncludePath(StringRef base) {
+  std::error_code EC;
+  int MaxVersion = 0;
+  std::string MaxVersionString = "";
+  for (llvm::sys::fs::directory_iterator LI(base, EC), LE; !EC && LI != LE;
+       LI = LI.increment(EC)) {
+    StringRef VersionText = llvm::sys::path::filename(LI->path());
+    int Version;
+    if (VersionText[0] == 'v' &&
+        !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
+      if (Version > MaxVersion) {
+        MaxVersion = Version;
+        MaxVersionString = VersionText;
+      }
+    }
+  }
+  return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
+}
+
 void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
                                          ArgStringList &CC1Args) const {
   if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
@@ -3858,17 +3877,14 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
   // Check if libc++ has been enabled and provide its include paths if so.
   if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
     const std::string LibCXXIncludePathCandidates[] = {
-        // The primary location is within the Clang installation.
-        // FIXME: We shouldn't hard code 'v1' here to make Clang future proof to
-        // newer ABI versions.
-        getDriver().Dir + "/../include/c++/v1",
+        DetectLibcxxIncludePath(getDriver().Dir + "/../include/c++"),
 
         // We also check the system as for a long time this is the only place
         // Clang looked.
         // FIXME: We should really remove this. It doesn't make any sense.
-        getDriver().SysRoot + "/usr/include/c++/v1"};
+        DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/include/c++")};
     for (const auto &IncludePath : LibCXXIncludePathCandidates) {
-      if (!getVFS().exists(IncludePath))
+      if (IncludePath.empty() || !getVFS().exists(IncludePath))
         continue;
       // Add the first candidate that exists.
       addSystemInclude(DriverArgs, CC1Args, IncludePath);
diff --git a/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/bin/.keep b/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/bin/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/include/c++/v1/.keep b/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/include/c++/v1/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/include/c++/v2/.keep b/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/include/c++/v2/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/lib/.keep b/test/Driver/Inputs/basic_linux_libcxxv2_tree/usr/lib/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/bin/.keep b/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/bin/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/4.8/backward/.keep b/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/4.8/backward/.keep
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/v1/.keep b/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/v1/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/v2/.keep b/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/include/c++/v2/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/lib/.keep b/test/Driver/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr/lib/.keep
new file mode 100644 (file)
index 0000000..e69de29
index 23912cb94aeff1b2004ce6b69fcdba0120b05af0..bd1da4976d12a818565887d4fbfaf3cb4cc1ac7a 100644 (file)
 // CHECK-BASIC-LIBCXX-INSTALL: "-internal-isystem" "[[SYSROOT]]/usr/bin/../include/c++/v1"
 // CHECK-BASIC-LIBCXX-INSTALL: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
 //
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN:     -target x86_64-unknown-linux-gnu \
+// RUN:     -stdlib=libc++ \
+// RUN:     -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
+// RUN:     --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \
+// RUN:     --gcc-toolchain="" \
+// RUN:   | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-SYSROOT %s
+// CHECK-BASIC-LIBCXXV2-SYSROOT: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK-BASIC-LIBCXXV2-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-BASIC-LIBCXXV2-SYSROOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v2"
+// CHECK-BASIC-LIBCXXV2-SYSROOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN:     -target x86_64-unknown-linux-gnu \
+// RUN:     -stdlib=libc++ \
+// RUN:     -ccc-install-dir %S/Inputs/basic_linux_libcxxv2_tree/usr/bin \
+// RUN:     --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \
+// RUN:     --gcc-toolchain="" \
+// RUN:   | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-INSTALL %s
+// CHECK-BASIC-LIBCXXV2-INSTALL: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK-BASIC-LIBCXXV2-INSTALL: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-BASIC-LIBCXXV2-INSTALL: "-internal-isystem" "[[SYSROOT]]/usr/bin/../include/c++/v2"
+// CHECK-BASIC-LIBCXXV2-INSTALL: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+//
+// Test Linux with both libc++ and libstdc++ installed.
+// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
+// RUN:     -target x86_64-unknown-linux-gnu \
+// RUN:     -stdlib=libc++ \
+// RUN:     -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
+// RUN:     --sysroot=%S/Inputs/basic_linux_libstdcxx_libcxxv2_tree \
+// RUN:     --gcc-toolchain="" \
+// RUN:   | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT %s
+// CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "{{[^"]*}}clang{{[^"]*}}" "-cc1"
+// CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v2"
+// CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+//
 // Test a very broken version of multiarch that shipped in Ubuntu 11.04.
 // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \
 // RUN:     -target i386-unknown-linux \