>From e62596ca5011955bf17f297227038dbfc5a9f8e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= <tor.arne.vestbo@nokia.com>
Date: Fri, 15 Oct 2010 11:32:54 +0200
Subject: [PATCH v2] Add Clang driver-support for directory-style precompiled headers

When passed -include foo we will check if foo.pch is a directory,
and if so try to look up a precompiled header matching the current
input language in that directory.

GCC will actually search every file in this directory, regardless of
naming, and choose the first one that matches the language.
---
 include/clang/Basic/DiagnosticDriverKinds.td |    2 +
 lib/Driver/Tools.cpp                         |   10 ++++++++
 test/Driver/pch.c                            |   33 ++++++++++++++++++++++++++
 test/Driver/pth.c                            |   21 ++++++++++++++++
 4 files changed, 66 insertions(+), 0 deletions(-)
 create mode 100644 test/Driver/pch.c

diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 748a3db..4265ec8 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -104,5 +104,7 @@ def warn_drv_objc_gc_unsupported : Warning<
   "Objective-C garbage collection is not supported on this platform, ignoring '%0'">;
 def warn_drv_pch_not_first_include : Warning<
   "precompiled header '%0' was ignored because '%1' is not first '-include'">;
+def warn_drv_pch_missing_language : Warning<
+  "ignoring argument '%0' due to missing precompiled header '%1' for language '%2'">;
 
 }
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 31f9c08..0154d86 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -256,6 +256,16 @@ void Clang::AddPreprocessingOptions(const Driver &D,
       if (FoundPCH || FoundPTH) {
         if (IsFirstImplicitInclude) {
           A->claim();
+          if (P.isDirectory()) {
+            // Expect to find a precompiled header matching the current input type
+            P.appendComponent(types::getTypeName(Inputs[0].getType()));
+            if (!P.exists()) {
+              D.Diag(clang::diag::warn_drv_pch_missing_language)
+                  << A->getAsString(Args) << P.str()
+                  << types::getTypeName(Inputs[0].getType());
+              continue;
+            }
+          }
           if (UsePCH)
             CmdArgs.push_back("-include-pch");
           else
diff --git a/test/Driver/pch.c b/test/Driver/pch.c
new file mode 100644
index 0000000..e80e658
--- /dev/null
+++ b/test/Driver/pch.c
@@ -0,0 +1,33 @@
+// Test transparent PCH support.
+
+// RUN: %clang -x c-header %s -o %t.h.pch -### 2> %t.log
+// RUN: FileCheck -check-prefix CHECK1 -input-file %t.log %s
+
+// CHECK1: "{{.*}}/clang{{.*}}" "-cc1" {{.*}} "-o" "{{.*}}.h.pch" "-x" "c-header" "{{.*}}pch.c"
+
+// RUN: touch %t.h.pch
+// RUN: %clang -E -include %t.h %s -### 2> %t.log
+// RUN: FileCheck -check-prefix CHECK2 -input-file %t.log %s
+
+// CHECK2: "{{.*}}/clang{{.*}}" "-cc1" {{.*}}"-include-pch" "{{.*}}.h.pch" {{.*}}"-x" "c" "{{.*}}pch.c"
+
+// RUN: mkdir -p %t.pch
+// RUN: %clang -x c-header %s -o %t.pch/c -### 2> %t.log
+// RUN: FileCheck -check-prefix CHECK3 -input-file %t.log %s
+
+// CHECK3: "{{.*}}/clang{{.*}}" "-cc1" {{.*}} "-o" "{{.*}}.pch/c" "-x" "c-header" "{{.*}}pch.c"
+
+// RUN: rm -f %t.pch/c
+// RUN: %clang -E -include %t %s -### 2> %t.log
+// RUN: echo "DONE" >> %t.log
+// RUN: FileCheck -check-prefix CHECK4 -input-file %t.log %s
+
+// CHECK4: {{.*}} ignoring argument '-include {{.*}}' due to missing precompiled header '{{.*}}.pch/c' for language 'c'
+// CHECK4-NOT: -include-pch
+// CHECK4: DONE
+
+// RUN: touch %t.pch/c
+// RUN: %clang -E -include %t %s -### 2> %t.log
+// RUN: FileCheck -check-prefix CHECK5 -input-file %t.log %s
+
+// CHECK5: "{{.*}}/clang{{.*}}" "-cc1" {{.*}}"-include-pch" "{{.*}}.pch/c" {{.*}}"-x" "c" "{{.*}}pch.c"
diff --git a/test/Driver/pth.c b/test/Driver/pth.c
index 9c47c55..d6ed904 100644
--- a/test/Driver/pth.c
+++ b/test/Driver/pth.c
@@ -10,3 +10,24 @@
 // RUN: FileCheck -check-prefix CHECK2 -input-file %t.log %s
 
 // CHECK2: "{{.*}}/clang{{.*}}" "-cc1" {{.*}}"-include-pth" "{{.*}}.h.pth" {{.*}}"-x" "c" "{{.*}}pth.c"
+
+// RUN: mkdir -p %t.pth
+// RUN: %clang -ccc-pch-is-pth -x c-header %s -o %t.pth/c -### 2> %t.log
+// RUN: FileCheck -check-prefix CHECK3 -input-file %t.log %s
+
+// CHECK3: "{{.*}}/clang{{.*}}" "-cc1" {{.*}} "-o" "{{.*}}.pth/c" "-x" "c-header" "{{.*}}pth.c"
+
+// RUN: rm -f %t.pth/c
+// RUN: %clang -ccc-pch-is-pth -E -include %t %s -### 2> %t.log
+// RUN: echo "DONE" >> %t.log
+// RUN: FileCheck -check-prefix CHECK4 -input-file %t.log %s
+
+// CHECK4: {{.*}} ignoring argument '-include {{.*}}' due to missing precompiled header '{{.*}}.pth/c' for language 'c'
+// CHECK4-NOT: -include-pth
+// CHECK4: DONE
+
+// RUN: touch %t.pth/c
+// RUN: %clang -ccc-pch-is-pth -E -include %t %s -### 2> %t.log
+// RUN: FileCheck -check-prefix CHECK5 -input-file %t.log %s
+
+// CHECK5: "{{.*}}/clang{{.*}}" "-cc1" {{.*}}"-include-pth" "{{.*}}.pth/c" {{.*}}"-x" "c" "{{.*}}pth.c"
-- 
1.7.2.1


