From 8cd452d47137f94c2d00e9dccf11a3deb1c12f05 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 30 Aug 2016 18:55:16 +0000 Subject: [PATCH] PR30195: Fix clang-cl attempting to precompile bogus (non-precompilable) input types. llvm-svn: 280133 --- clang/include/clang/Driver/Types.h | 4 +++ clang/lib/Driver/Driver.cpp | 8 ++++-- clang/lib/Driver/Types.cpp | 18 ++++++++++++++ clang/test/Driver/cl-pch.c | 51 ++++++++++++++++++++------------------ 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h index 22122c7..c8f0b56 100644 --- a/clang/include/clang/Driver/Types.h +++ b/clang/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/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 9871f29..a1adb67 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/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/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index e6072de..1588c94 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/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/clang/test/Driver/cl-pch.c b/clang/test/Driver/cl-pch.c index 3372c18..339b7a6 100644 --- a/clang/test/Driver/cl-pch.c +++ b/clang/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 -- 2.7.4