From: Richard Smith Date: Tue, 30 Aug 2016 18:55:16 +0000 (+0000) Subject: PR30195: Fix clang-cl attempting to precompile bogus (non-precompilable) input types. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0c25e2545416359c181e3486ea7000fc63cdabb9;p=clang PR30195: Fix clang-cl attempting to precompile bogus (non-precompilable) input types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@280133 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index 22122c7a8e..c8f0b5664f 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -90,6 +90,10 @@ namespace types { /// C type (used for clang++ emulation of g++ behaviour) ID lookupCXXTypeForCType(ID Id); + /// Lookup header file input type that corresponds to given + /// source file type (used for clang-cl emulation of \Yc). + ID lookupHeaderTypeForSourceType(ID Id); + } // end namespace types } // end namespace driver } // end namespace clang diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 9871f29eb3..a1adb676a3 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1685,12 +1685,14 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, if (YcArg) { // Add a separate precompile phase for the compile phase. if (FinalPhase >= phases::Compile) { + const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType); llvm::SmallVector PCHPL; - types::getCompilationPhases(types::TY_CXXHeader, PCHPL); + types::getCompilationPhases(HeaderType, PCHPL); Arg *PchInputArg = MakeInputArg(Args, Opts, YcArg->getValue()); // Build the pipeline for the pch file. - Action *ClangClPch = C.MakeAction(*PchInputArg, InputType); + Action *ClangClPch = + C.MakeAction(*PchInputArg, HeaderType); for (phases::ID Phase : PCHPL) ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch); assert(ClangClPch); @@ -1812,6 +1814,8 @@ Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args, return C.MakeAction(Input, OutputTy); } case phases::Precompile: { + assert(onlyPrecompileType(Input->getType()) && + "asked to precompile non-precompilable type"); types::ID OutputTy = types::TY_PCH; if (Args.hasArg(options::OPT_fsyntax_only)) { // Syntax checks should not emit a PCH file diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp index e6072de34e..1588c94ac7 100644 --- a/lib/Driver/Types.cpp +++ b/lib/Driver/Types.cpp @@ -259,3 +259,21 @@ ID types::lookupCXXTypeForCType(ID Id) { return types::TY_PP_CXXHeader; } } + +ID types::lookupHeaderTypeForSourceType(ID Id) { + switch (Id) { + default: + return Id; + + case types::TY_C: + return types::TY_CHeader; + case types::TY_CXX: + return types::TY_CXXHeader; + case types::TY_ObjC: + return types::TY_ObjCHeader; + case types::TY_ObjCXX: + return types::TY_ObjCXXHeader; + case types::TY_CL: + return types::TY_CLHeader; + } +} diff --git a/test/Driver/cl-pch.c b/test/Driver/cl-pch.c index 3372c184bb..339b7a6efd 100644 --- a/test/Driver/cl-pch.c +++ b/test/Driver/cl-pch.c @@ -1,3 +1,6 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// // Note: %s and %S must be preceded by --, otherwise it may be interpreted as a // command-line option, e.g. on Mac where %s is commonly under /Users. @@ -5,41 +8,41 @@ // a few things for .c inputs. // /Yc with a .c file should build a c pch file. -// RUN: %clang_cl -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \ +// RUN: %clang_cl -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YC %s // CHECK-YC: cc1 -// CHECK-YC: -emit-pch -// CHECK-YC: -o -// CHECK-YC: pchfile.pch -// CHECK-YC: -x -// CHECK-YC: "c" +// CHECK-YC-SAME: -emit-pch +// CHECK-YC-SAME: -o +// CHECK-YC-SAME: pchfile.pch +// CHECK-YC-SAME: -x +// CHECK-YC-SAME: c-header // But not if /TP changes the input language to C++. -// RUN: %clang_cl /TP -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \ +// RUN: %clang_cl /TP -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YCTP %s // CHECK-YCTP: cc1 -// CHECK-YCTP: -emit-pch -// CHECK-YCTP: -o -// CHECK-YCTP: pchfile.pch -// CHECK-YCTP: -x -// CHECK-YCTP: "c++" +// CHECK-YCTP-SAME: -emit-pch +// CHECK-YCTP-SAME: -o +// CHECK-YCTP-SAME: pchfile.pch +// CHECK-YCTP-SAME: -x +// CHECK-YCTP-SAME: c++-header // Except if a later /TC changes it back. -// RUN: %clang_cl -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \ +// RUN: %clang_cl -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v -- %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YCTPTC %s // CHECK-YCTPTC: cc1 -// CHECK-YCTPTC: -emit-pch -// CHECK-YCTPTC: -o -// CHECK-YCTPTC: pchfile.pch -// CHECK-YCTPTC: -x -// CHECK-YCTPTC: "c" +// CHECK-YCTPTC-SAME: -emit-pch +// CHECK-YCTPTC-SAME: -o +// CHECK-YCTPTC-SAME: pchfile.pch +// CHECK-YCTPTC-SAME: -x +// CHECK-YCTPTC-SAME: c-header // Also check lower-case /Tp flag. -// RUN: %clang_cl -Werror /Tp%s /Ycpchfile.h /FIpchfile.h /c -### 2>&1 \ +// RUN: %clang_cl -Werror /Tp%s /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-YCTp %s // CHECK-YCTp: cc1 -// CHECK-YCTp: -emit-pch -// CHECK-YCTp: -o -// CHECK-YCTp: pchfile.pch -// CHECK-YCTp: -x -// CHECK-YCTp: "c++" +// CHECK-YCTp-SAME: -emit-pch +// CHECK-YCTp-SAME: -o +// CHECK-YCTp-SAME: pchfile.pch +// CHECK-YCTp-SAME: -x +// CHECK-YCTp-SAME: c++-header