<div dir="ltr">Btw, this seems to create cuda actions when building with -fsynatx-only (this is breaking tools that operate on cuda code, because they get  an error that only one compile action is expected).<div><br><div class="gmail_quote"><div dir="ltr">On Tue, Jul 14, 2015 at 8:43 AM Justin Bogner <<a href="mailto:mail@justinbogner.com" target="_blank">mail@justinbogner.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Artem Belevich <<a href="mailto:tra@google.com" target="_blank">tra@google.com</a>> writes:<br>
> Author: tra<br>
> Date: Mon Jul 13 18:27:56 2015<br>
> New Revision: 242085<br>
><br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D242085-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=n86G5mEAJ9s0ikfRT1absPVmNPYjSGBakYbH86B22Vg&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=242085&view=rev</a><br>
> Log:<br>
> [cuda] Driver changes to compile and stitch together host and device-side CUDA code.<br>
><br>
>   NOTE: reverts r242077 to reinstate r242058, r242065, 242067<br>
>         and includes fix for OS X test failures.<br>
><br>
>   - Changed driver pipeline to compile host and device side of CUDA<br>
>     files and incorporate results of device-side compilation into host<br>
>     object file.<br>
><br>
>   - Added a test for cuda pipeline creation in clang driver.<br>
><br>
>   New clang options:<br>
>   --cuda-host-only   - Do host-side compilation only.<br>
>   --cuda-device-only - Do device-side compilation only.<br>
><br>
>   --cuda-gpu-arch=<ARCH> - specify GPU architecture for device-side<br>
>     compilation. E.g. sm_35, sm_30. Default is sm_20. May be used more<br>
>     than once in which case one device-compilation will be done per<br>
>     unique specified GPU architecture.<br>
><br>
>   Differential Revision: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_D9509&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=WDZ8ek1Ld-BGQdaVQW36Kddq-tnuTGgtLmj3LJL3Mbo&e=" rel="noreferrer" target="_blank">http://reviews.llvm.org/D9509</a><br>
><br>
> Added:<br>
>     cfe/trunk/test/Driver/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__cuda-2Doptions.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=JETtyv_A1yjmTD_KmoFDoStKOHa9fmHDH6OI0wsJLU8&e=" rel="noreferrer" target="_blank">cuda-options.cu</a><br>
>     cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__index-2Dfile.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=Z26JivvnfsF4tloeePDLQLHxsFQrEclL-D6_alidUsQ&e=" rel="noreferrer" target="_blank">index-file.cu</a><br>
> Modified:<br>
>     cfe/trunk/include/clang/Driver/Action.h<br>
>     cfe/trunk/include/clang/Driver/Options.td<br>
>     cfe/trunk/include/clang/Driver/Types.def<br>
>     cfe/trunk/include/clang/Driver/Types.h<br>
>     cfe/trunk/lib/Driver/Action.cpp<br>
>     cfe/trunk/lib/Driver/Driver.cpp<br>
>     cfe/trunk/lib/Driver/ToolChain.cpp<br>
>     cfe/trunk/lib/Driver/ToolChains.cpp<br>
>     cfe/trunk/lib/Driver/ToolChains.h<br>
>     cfe/trunk/lib/Driver/Tools.cpp<br>
>     cfe/trunk/lib/Driver/Types.cpp<br>
>     cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp<br>
>     cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__attributes-2Dcuda.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=mTykXFMrswBOTJhzDBRffZ1C-BvcUHI5JLq6wIBSfbg&e=" rel="noreferrer" target="_blank">attributes-cuda.cu</a><br>
>     cfe/trunk/tools/libclang/CIndex.cpp<br>
>     cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h<br>
><br>
> Modified: cfe/trunk/include/clang/Driver/Action.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Driver_Action.h-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=vtHhQFgm5Qwu2PCa9zRkNf9giuN7kDBY0YAbrTGvHXU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Action.h?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Driver/Action.h (original)<br>
> +++ cfe/trunk/include/clang/Driver/Action.h Mon Jul 13 18:27:56 2015<br>
> @@ -41,6 +41,8 @@ public:<br>
>    enum ActionClass {<br>
>      InputClass = 0,<br>
>      BindArchClass,<br>
> +    CudaDeviceClass,<br>
> +    CudaHostClass,<br>
>      PreprocessJobClass,<br>
>      PrecompileJobClass,<br>
>      AnalyzeJobClass,<br>
> @@ -133,6 +135,41 @@ public:<br>
>    }<br>
>  };<br>
><br>
> +class CudaDeviceAction : public Action {<br>
> +  virtual void anchor();<br>
> +  /// GPU architecture to bind -- e.g 'sm_35'.<br>
> +  const char *GpuArchName;<br>
> +  /// True when action results are not consumed by the host action (e.g when<br>
> +  /// -fsyntax-only or --cuda-device-only options are used).<br>
> +  bool AtTopLevel;<br>
> +<br>
> +public:<br>
> +  CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName,<br>
> +                   bool AtTopLevel);<br>
> +<br>
> +  const char *getGpuArchName() const { return GpuArchName; }<br>
> +  bool isAtTopLevel() const { return AtTopLevel; }<br>
> +<br>
> +  static bool classof(const Action *A) {<br>
> +    return A->getKind() == CudaDeviceClass;<br>
> +  }<br>
> +};<br>
> +<br>
> +class CudaHostAction : public Action {<br>
> +  virtual void anchor();<br>
> +  ActionList DeviceActions;<br>
> +<br>
> +public:<br>
> +  CudaHostAction(std::unique_ptr<Action> Input,<br>
> +                 const ActionList &DeviceActions);<br>
> +  ~CudaHostAction() override;<br>
> +<br>
> +  ActionList &getDeviceActions() { return DeviceActions; }<br>
> +  const ActionList &getDeviceActions() const { return DeviceActions; }<br>
> +<br>
> +  static bool classof(const Action *A) { return A->getKind() == CudaHostClass; }<br>
> +};<br>
> +<br>
>  class JobAction : public Action {<br>
>    virtual void anchor();<br>
>  protected:<br>
><br>
> Modified: cfe/trunk/include/clang/Driver/Options.td<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Driver_Options.td-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=1MRIlu0X9xy9Or54b4zLvE6SaBFx8eRFMa2VZzjakQw&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Driver/Options.td (original)<br>
> +++ cfe/trunk/include/clang/Driver/Options.td Mon Jul 13 18:27:56 2015<br>
> @@ -351,6 +351,12 @@ def cxx_isystem : JoinedOrSeparate<["-"]<br>
>    MetaVarName<"<directory>">;<br>
>  def c : Flag<["-"], "c">, Flags<[DriverOption]>,<br>
>    HelpText<"Only run preprocess, compile, and assemble steps">;<br>
> +def cuda_device_only : Flag<["--"], "cuda-device-only">,<br>
> +  HelpText<"Do device-side CUDA compilation only">;<br>
> +def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">,<br>
> +  Flags<[DriverOption, HelpHidden]>, HelpText<"CUDA GPU architecture">;<br>
> +def cuda_host_only : Flag<["--"], "cuda-host-only">,<br>
> +  HelpText<"Do host-side CUDA compilation only">;<br>
>  def dA : Flag<["-"], "dA">, Group<d_Group>;<br>
>  def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,<br>
>    HelpText<"Print macro definitions in -E mode in addition to normal output">;<br>
><br>
> Modified: cfe/trunk/include/clang/Driver/Types.def<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Driver_Types.def-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=ZA_-9prtGSwjxyxYprruQhlLCw4qlQxdm8iD3MnfVHg&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Types.def?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Driver/Types.def (original)<br>
> +++ cfe/trunk/include/clang/Driver/Types.def Mon Jul 13 18:27:56 2015<br>
> @@ -44,6 +44,7 @@ TYPE("c",                        C,<br>
>  TYPE("cl",                       CL,           PP_C,            "cl",    "u")<br>
>  TYPE("cuda-cpp-output",          PP_CUDA,      INVALID,         "cui",   "u")<br>
>  TYPE("cuda",                     CUDA,         PP_CUDA,         "cu",    "u")<br>
> +TYPE("cuda",                     CUDA_DEVICE,  PP_CUDA,         "cu",    "")<br>
>  TYPE("objective-c-cpp-output",   PP_ObjC,      INVALID,         "mi",    "u")<br>
>  TYPE("objc-cpp-output",          PP_ObjC_Alias, INVALID,        "mi",    "u")<br>
>  TYPE("objective-c",              ObjC,         PP_ObjC,         "m",     "u")<br>
><br>
> Modified: cfe/trunk/include/clang/Driver/Types.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Driver_Types.h-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=MRbkm5exCU3h3iLWd3Gcx44y-ap92liIEwXTOMoKAQs&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Types.h?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Driver/Types.h (original)<br>
> +++ cfe/trunk/include/clang/Driver/Types.h Mon Jul 13 18:27:56 2015<br>
> @@ -63,6 +63,9 @@ namespace types {<br>
>    /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).<br>
>    bool isCXX(ID Id);<br>
><br>
> +  /// isCuda - Is this a CUDA input.<br>
> +  bool isCuda(ID Id);<br>
> +<br>
>    /// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).<br>
>    bool isObjC(ID Id);<br>
><br>
><br>
> Modified: cfe/trunk/lib/Driver/Action.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Driver_Action.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=wqdIvIUiipcMnu3xYygaEDHjM6ohCAVUX2K7e4ULSpo&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Action.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Driver/Action.cpp (original)<br>
> +++ cfe/trunk/lib/Driver/Action.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -24,6 +24,8 @@ const char *Action::getClassName(ActionC<br>
>    switch (AC) {<br>
>    case InputClass: return "input";<br>
>    case BindArchClass: return "bind-arch";<br>
> +  case CudaDeviceClass: return "cuda-device";<br>
> +  case CudaHostClass: return "cuda-host";<br>
>    case PreprocessJobClass: return "preprocessor";<br>
>    case PrecompileJobClass: return "precompiler";<br>
>    case AnalyzeJobClass: return "analyzer";<br>
> @@ -53,6 +55,25 @@ BindArchAction::BindArchAction(std::uniq<br>
>                                 const char *_ArchName)<br>
>      : Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {}<br>
><br>
> +void CudaDeviceAction::anchor() {}<br>
> +<br>
> +CudaDeviceAction::CudaDeviceAction(std::unique_ptr<Action> Input,<br>
> +                                   const char *ArchName, bool AtTopLevel)<br>
> +    : Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName),<br>
> +      AtTopLevel(AtTopLevel) {}<br>
> +<br>
> +void CudaHostAction::anchor() {}<br>
> +<br>
> +CudaHostAction::CudaHostAction(std::unique_ptr<Action> Input,<br>
> +                               const ActionList &_DeviceActions)<br>
<br>
Identifiers starting with an underscore than a capital are reserved.<br>
Please just call this DeviceActions.<br>
<br>
> +    : Action(CudaHostClass, std::move(Input)), DeviceActions(_DeviceActions) {}<br>
> +<br>
> +CudaHostAction::~CudaHostAction() {<br>
> +  for (iterator it = DeviceActions.begin(), ie = DeviceActions.end(); it != ie;<br>
<br>
We usually name variables starting with a capital letter, so these<br>
should probably be `I` and `E` rather than `it` and `ie`. Might as well<br>
use auto here as well, since they're just iterators.<br>
<br>
This applies in several places later in this patch too. Please clean<br>
them up.<br>
<br>
> +       ++it)<br>
> +    delete *it;<br>
> +}<br>
> +<br>
>  void JobAction::anchor() {}<br>
><br>
>  JobAction::JobAction(ActionClass Kind, std::unique_ptr<Action> Input,<br>
><br>
> Modified: cfe/trunk/lib/Driver/Driver.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Driver_Driver.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=-CzdHSqTWN30s5-qcBE0JFP-chY9pWXeFANVzz2hNlI&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Driver/Driver.cpp (original)<br>
> +++ cfe/trunk/lib/Driver/Driver.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -174,8 +174,10 @@ phases::ID Driver::getFinalPhase(const D<br>
>    } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {<br>
>      FinalPhase = phases::Backend;<br>
><br>
> -    // -c only runs up to the assembler.<br>
> -  } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {<br>
> +    // -c and partial CUDA compilations only run up to the assembler.<br>
> +  } else if ((PhaseArg = DAL.getLastArg(options::OPT_c)) ||<br>
> +             (PhaseArg = DAL.getLastArg(options::OPT_cuda_device_only)) ||<br>
> +             (PhaseArg = DAL.getLastArg(options::OPT_cuda_host_only))) {<br>
>      FinalPhase = phases::Assemble;<br>
><br>
>      // Otherwise do everything.<br>
> @@ -900,9 +902,20 @@ static unsigned PrintActions1(const Comp<br>
>    } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {<br>
>      os << '"' << BIA->getArchName() << '"' << ", {"<br>
>         << PrintActions1(C, *BIA->begin(), Ids) << "}";<br>
> +  } else if (CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {<br>
> +    os << '"' << CDA->getGpuArchName() << '"' << ", {"<br>
> +       << PrintActions1(C, *CDA->begin(), Ids) << "}";<br>
>    } else {<br>
> +    ActionList *AL;<br>
> +    if (CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {<br>
> +      os << "{" << PrintActions1(C, *CHA->begin(), Ids) << "}"<br>
> +         << ", gpu binaries ";<br>
> +      AL = &CHA->getDeviceActions();<br>
> +    } else<br>
> +      AL = &A->getInputs();<br>
> +<br>
>      const char *Prefix = "{";<br>
> -    for (Action *PreRequisite : *A) {<br>
> +    for (Action *PreRequisite : *AL) {<br>
>        os << Prefix << PrintActions1(C, PreRequisite, Ids);<br>
>        Prefix = ", ";<br>
>      }<br>
> @@ -1215,6 +1228,93 @@ void Driver::BuildInputs(const ToolChain<br>
>    }<br>
>  }<br>
><br>
> +// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE input<br>
> +// action and then wraps each in CudaDeviceAction paired with appropriate GPU<br>
> +// arch name. If we're only building device-side code, each action remains<br>
> +// independent. Otherwise we pass device-side actions as inputs to a new<br>
> +// CudaHostAction which combines both host and device side actions.<br>
> +static std::unique_ptr<Action><br>
> +buildCudaActions(const Driver &D, const ToolChain &TC, DerivedArgList &Args,<br>
> +                 const Arg *InputArg, const types::ID InputType,<br>
> +                 std::unique_ptr<Action> Current, ActionList &Actions) {<br>
> +<br>
> +  assert(InputType == types::TY_CUDA &&<br>
> +         "CUDA Actions only apply to CUDA inputs.");<br>
> +<br>
> +  // Collect all cuda_gpu_arch parameters, removing duplicates.<br>
> +  SmallVector<const char *, 4> GpuArchList;<br>
> +  llvm::StringSet<> GpuArchNames;<br>
> +  for (Arg *A : Args) {<br>
> +    if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) {<br>
> +      A->claim();<br>
> +      if (GpuArchNames.insert(A->getValue()).second)<br>
> +        GpuArchList.push_back(A->getValue());<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // Default to sm_20 which is the lowest common denominator for supported GPUs.<br>
> +  // sm_20 code should work correctly, if suboptimally, on all newer GPUs.<br>
> +  if (GpuArchList.empty())<br>
> +    GpuArchList.push_back("sm_20");<br>
> +<br>
> +  // Replicate inputs for each GPU architecture.<br>
> +  Driver::InputList CudaDeviceInputs;<br>
> +  for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)<br>
> +    CudaDeviceInputs.push_back(std::make_pair(types::TY_CUDA_DEVICE, InputArg));<br>
> +<br>
> +  // Build actions for all device inputs.<br>
> +  ActionList CudaDeviceActions;<br>
> +  D.BuildActions(TC, Args, CudaDeviceInputs, CudaDeviceActions);<br>
> +  assert(GpuArchList.size() == CudaDeviceActions.size() &&<br>
> +         "Failed to create actions for all devices");<br>
> +<br>
> +  // Check whether any of device actions stopped before they could generate PTX.<br>
> +  bool PartialCompilation = false;<br>
> +  bool DeviceOnlyCompilation = Args.hasArg(options::OPT_cuda_device_only);<br>
<br>
The ordering here is confusing - it looks like DeviceOnlyCompilation is<br>
related to the loop that sets PartialCompilation.<br>
<br>
> +  for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i) {<br>
> +    if (CudaDeviceActions[i]->getKind() != Action::BackendJobClass) {<br>
> +      PartialCompilation = true;<br>
> +      break;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // Figure out what to do with device actions -- pass them as inputs to the<br>
> +  // host action or run each of them independently.<br>
> +  if (PartialCompilation || DeviceOnlyCompilation) {<br>
> +    // In case of partial or device-only compilation results of device actions<br>
> +    // are not consumed by the host action device actions have to be added to<br>
> +    // top-level actions list with AtTopLevel=true and run independently.<br>
> +<br>
> +    // -o is ambiguous if we have more than one top-level action.<br>
> +    if (Args.hasArg(options::OPT_o) &&<br>
> +        (!DeviceOnlyCompilation || GpuArchList.size() > 1)) {<br>
> +      D.Diag(clang::diag::err_drv_output_argument_with_multiple_files);<br>
> +      return nullptr;<br>
> +    }<br>
> +<br>
> +    for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)<br>
> +      Actions.push_back(<br>
> +          new CudaDeviceAction(std::unique_ptr<Action>(CudaDeviceActions[i]),<br>
> +                               GpuArchList[i], /* AtTopLevel */ true));<br>
> +    // Kill host action in case of device-only compilation.<br>
> +    if (DeviceOnlyCompilation)<br>
> +      Current.reset(nullptr);<br>
> +    return Current;<br>
> +  } else {<br>
<br>
Since the `if` returns unconditionally, an early exit is better than an<br>
else.<br>
<br>
> +    // Outputs of device actions during complete CUDA compilation get created<br>
> +    // with AtTopLevel=false and become inputs for the host action.<br>
> +    ActionList DeviceActions;<br>
> +    for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)<br>
> +      DeviceActions.push_back(<br>
> +          new CudaDeviceAction(std::unique_ptr<Action>(CudaDeviceActions[i]),<br>
> +                               GpuArchList[i], /* AtTopLevel */ false));<br>
> +    // Return a new host action that incorporates original host action and all<br>
> +    // device actions.<br>
> +    return std::unique_ptr<Action>(<br>
> +        new CudaHostAction(std::move(Current), DeviceActions));<br>
> +  }<br>
> +}<br>
> +<br>
>  void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,<br>
>                            const InputList &Inputs, ActionList &Actions) const {<br>
>    llvm::PrettyStackTraceString CrashInfo("Building compilation actions");<br>
> @@ -1312,6 +1412,25 @@ void Driver::BuildActions(const ToolChai<br>
>        continue;<br>
>      }<br>
><br>
> +    phases::ID CudaInjectionPhase;<br>
> +    if (isSaveTempsEnabled()) {<br>
> +      // All phases are done independently, inject GPU blobs during compilation<br>
> +      // phase as that's where we generate glue code to init them.<br>
> +      CudaInjectionPhase = phases::Compile;<br>
> +    } else {<br>
> +      // Assumes that clang does everything up until linking phase, so we inject<br>
> +      // cuda device actions at the last step before linking. Otherwise CUDA<br>
> +      // host action forces preprocessor into a separate invocation.<br>
> +      if (FinalPhase == phases::Link) {<br>
<br>
This is `else if`. Nesting the if inside the else is confusing.<br>
<br>
> +        for (auto i = PL.begin(), e = PL.end(); i != e; ++i) {<br>
> +          auto next = i + 1;<br>
> +          if (next != e && *next == phases::Link)<br>
<br>
What if i == e?<br>
<br>
> +            CudaInjectionPhase = *i;<br>
> +        }<br>
> +      } else<br>
> +        CudaInjectionPhase = FinalPhase;<br>
> +    }<br>
> +<br>
>      // Build the pipeline for this file.<br>
>      std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType));<br>
>      for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();<br>
> @@ -1337,6 +1456,15 @@ void Driver::BuildActions(const ToolChai<br>
><br>
>        // Otherwise construct the appropriate action.<br>
>        Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current));<br>
> +<br>
> +      if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase &&<br>
> +          !Args.hasArg(options::OPT_cuda_host_only)) {<br>
> +        Current = buildCudaActions(*this, TC, Args, InputArg, InputType,<br>
> +                                   std::move(Current), Actions);<br>
> +        if (!Current)<br>
> +          break;<br>
> +      }<br>
<br>
This whole block of code seems out of place. In fact, why doesn't CUDA<br>
just have its own phases::ID? It seems like that would simplify all of<br>
this.<br>
<br>
> +<br>
>        if (Current->getType() == types::TY_Nothing)<br>
>          break;<br>
>      }<br>
> @@ -1576,7 +1704,13 @@ static const Tool *SelectToolForJob(Comp<br>
>    if (isa<BackendJobAction>(JA)) {<br>
>      // Check if the compiler supports emitting LLVM IR.<br>
>      assert(Inputs->size() == 1);<br>
> -    JobAction *CompileJA = cast<CompileJobAction>(*Inputs->begin());<br>
> +    JobAction *CompileJA;<br>
> +    // Extract real host action, if it's a CudaHostAction.<br>
> +    if (CudaHostAction *CudaHA = dyn_cast<CudaHostAction>(*Inputs->begin()))<br>
> +      CompileJA = cast<CompileJobAction>(*CudaHA->begin());<br>
> +    else<br>
> +      CompileJA = cast<CompileJobAction>(*Inputs->begin());<br>
<br>
This seems kind of awkward. Not sure I have a better suggestion though.<br>
<br>
> +<br>
>      const Tool *Compiler = TC->SelectTool(*CompileJA);<br>
>      if (!Compiler)<br>
>        return nullptr;<br>
> @@ -1610,6 +1744,20 @@ void Driver::BuildJobsForAction(Compilat<br>
>                                  InputInfo &Result) const {<br>
>    llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");<br>
><br>
> +  InputInfoList CudaDeviceInputInfos;<br>
> +  if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {<br>
> +    InputInfo II;<br>
> +    // Append outputs of device jobs to the input list.<br>
> +    for (const Action *DA : CHA->getDeviceActions()) {<br>
> +      BuildJobsForAction(C, DA, TC, "", AtTopLevel,<br>
> +                         /*MultipleArchs*/ false, LinkingOutput, II);<br>
> +      CudaDeviceInputInfos.push_back(II);<br>
> +    }<br>
> +    // Override current action with a real host compile action and continue<br>
> +    // processing it.<br>
> +    A = *CHA->begin();<br>
> +  }<br>
> +<br>
>    if (const InputAction *IA = dyn_cast<InputAction>(A)) {<br>
>      // FIXME: It would be nice to not claim this here; maybe the old scheme of<br>
>      // just using Args was better?<br>
> @@ -1635,11 +1783,24 @@ void Driver::BuildJobsForAction(Compilat<br>
>      else<br>
>        TC = &C.getDefaultToolChain();<br>
><br>
> -    BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(), AtTopLevel,<br>
> +    BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,<br>
<br>
I guess this is just an unrelated cleanup? Better to commit those<br>
separately in the future.<br>
<br>
>                         MultipleArchs, LinkingOutput, Result);<br>
>      return;<br>
>    }<br>
><br>
> +  if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {<br>
> +    // Figure out which NVPTX triple to use for device-side compilation based on<br>
> +    // whether host is 64-bit.<br>
> +    llvm::Triple DeviceTriple(C.getDefaultToolChain().getTriple().isArch64Bit()<br>
> +                                  ? "nvptx64-nvidia-cuda"<br>
> +                                  : "nvptx-nvidia-cuda");<br>
<br>
It seems like a pretty bad layering violation to need to know these<br>
particular triples right here...<br>
<br>
Is getDefaultToolChain() even the right thing to do here? Isn't `TC`<br>
more appropriate?<br>
<br>
> +    BuildJobsForAction(C, *CDA->begin(),<br>
> +                       &getToolChain(C.getArgs(), DeviceTriple),<br>
> +                       CDA->getGpuArchName(), CDA->isAtTopLevel(),<br>
> +                       /*MultipleArchs*/ true, LinkingOutput, Result);<br>
> +    return;<br>
> +  }<br>
> +<br>
>    const ActionList *Inputs = &A->getInputs();<br>
><br>
>    const JobAction *JA = cast<JobAction>(A);<br>
> @@ -1671,6 +1832,10 @@ void Driver::BuildJobsForAction(Compilat<br>
>    if (JA->getType() == types::TY_dSYM)<br>
>      BaseInput = InputInfos[0].getFilename();<br>
><br>
> +  // Append outputs of cuda device jobs to the input list<br>
> +  if (CudaDeviceInputInfos.size())<br>
> +    InputInfos.append(CudaDeviceInputInfos.begin(), CudaDeviceInputInfos.end());<br>
> +<br>
>    // Determine the place to write output to, if any.<br>
>    if (JA->getType() == types::TY_Nothing)<br>
>      Result = InputInfo(A->getType(), BaseInput);<br>
> @@ -2052,6 +2217,9 @@ const ToolChain &Driver::getToolChain(co<br>
>          break;<br>
>        }<br>
>        break;<br>
> +    case llvm::Triple::CUDA:<br>
> +      TC = new toolchains::CudaToolChain(*this, Target, Args);<br>
> +      break;<br>
>      default:<br>
>        // Of these targets, Hexagon is the only one that might have<br>
>        // an OS of Linux, in which case it got handled above already.<br>
><br>
> Modified: cfe/trunk/lib/Driver/ToolChain.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Driver_ToolChain.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=qqzI495chQgaGHf5tBIJFYdjfnbBqT1xCg4lX1igKik&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChain.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Driver/ToolChain.cpp (original)<br>
> +++ cfe/trunk/lib/Driver/ToolChain.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -151,6 +151,8 @@ Tool *ToolChain::getTool(Action::ActionC<br>
><br>
>    case Action::InputClass:<br>
>    case Action::BindArchClass:<br>
> +  case Action::CudaDeviceClass:<br>
> +  case Action::CudaHostClass:<br>
>    case Action::LipoJobClass:<br>
>    case Action::DsymutilJobClass:<br>
>    case Action::VerifyDebugInfoJobClass:<br>
><br>
> Modified: cfe/trunk/lib/Driver/ToolChains.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Driver_ToolChains.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=M6UcaDzO1V5zfrGrbm-oagDHi1FgOIvQGwAWJltl778&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Driver/ToolChains.cpp (original)<br>
> +++ cfe/trunk/lib/Driver/ToolChains.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -3652,6 +3652,65 @@ Tool *DragonFly::buildLinker() const {<br>
>    return new tools::dragonfly::Linker(*this);<br>
>  }<br>
><br>
> +/// Stub for CUDA toolchain. At the moment we don't have assembler or<br>
> +/// linker and need toolchain mainly to propagate device-side options<br>
> +/// to CC1.<br>
> +<br>
> +CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,<br>
> +                             const ArgList &Args)<br>
> +    : Linux(D, Triple, Args) {}<br>
> +<br>
> +void<br>
> +CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,<br>
> +                                     llvm::opt::ArgStringList &CC1Args) const {<br>
> +  Linux::addClangTargetOptions(DriverArgs, CC1Args);<br>
> +  CC1Args.push_back("-fcuda-is-device");<br>
> +}<br>
> +<br>
> +llvm::opt::DerivedArgList *<br>
> +CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,<br>
> +                             const char *BoundArch) const {<br>
> +  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());<br>
> +  const OptTable &Opts = getDriver().getOpts();<br>
> +<br>
> +  for (Arg *A : Args) {<br>
> +    if (A->getOption().matches(options::OPT_Xarch__)) {<br>
> +      // Skip this argument unless the architecture matches BoundArch<br>
> +      if (A->getValue(0) != StringRef(BoundArch))<br>
> +        continue;<br>
> +<br>
> +      unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));<br>
> +      unsigned Prev = Index;<br>
> +      std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));<br>
> +<br>
> +      // If the argument parsing failed or more than one argument was<br>
> +      // consumed, the -Xarch_ argument's parameter tried to consume<br>
> +      // extra arguments. Emit an error and ignore.<br>
> +      //<br>
> +      // We also want to disallow any options which would alter the<br>
> +      // driver behavior; that isn't going to work in our model. We<br>
> +      // use isDriverOption() as an approximation, although things<br>
> +      // like -O4 are going to slip through.<br>
> +      if (!XarchArg || Index > Prev + 1) {<br>
> +        getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)<br>
> +            << A->getAsString(Args);<br>
> +        continue;<br>
> +      } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {<br>
> +        getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)<br>
> +            << A->getAsString(Args);<br>
> +        continue;<br>
> +      }<br>
> +      XarchArg->setBaseArg(A);<br>
> +      A = XarchArg.release();<br>
> +      DAL->AddSynthesizedArg(A);<br>
> +    }<br>
> +    DAL->append(A);<br>
> +  }<br>
> +<br>
> +  DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);<br>
> +  return DAL;<br>
> +}<br>
> +<br>
>  /// XCore tool chain<br>
>  XCore::XCore(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)<br>
>      : ToolChain(D, Triple, Args) {<br>
><br>
> Modified: cfe/trunk/lib/Driver/ToolChains.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Driver_ToolChains.h-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=ozln2maQC62P_Kc4R1iHZXtNIeMs9b33UDhfWr_8u_o&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Driver/ToolChains.h (original)<br>
> +++ cfe/trunk/lib/Driver/ToolChains.h Mon Jul 13 18:27:56 2015<br>
> @@ -699,6 +699,18 @@ private:<br>
>    std::string computeSysRoot() const;<br>
>  };<br>
><br>
> +class LLVM_LIBRARY_VISIBILITY CudaToolChain : public Linux {<br>
> +public:<br>
> +  CudaToolChain(const Driver &D, const llvm::Triple &Triple,<br>
> +                const llvm::opt::ArgList &Args);<br>
> +<br>
> +  llvm::opt::DerivedArgList *<br>
> +  TranslateArgs(const llvm::opt::DerivedArgList &Args,<br>
> +                const char *BoundArch) const override;<br>
> +  void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,<br>
> +                             llvm::opt::ArgStringList &CC1Args) const override;<br>
> +};<br>
> +<br>
>  class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux {<br>
>  protected:<br>
>    GCCVersion GCCLibAndIncVersion;<br>
><br>
> Modified: cfe/trunk/lib/Driver/Tools.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Driver_Tools.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=CwavFMr1KVZKGP2wUxyDOFt5ZPH6qp9lh94wZ7M_THo&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Driver/Tools.cpp (original)<br>
> +++ cfe/trunk/lib/Driver/Tools.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -1488,6 +1488,12 @@ static std::string getCPUName(const ArgL<br>
>      return CPUName;<br>
>    }<br>
><br>
> +  case llvm::Triple::nvptx:<br>
> +  case llvm::Triple::nvptx64:<br>
> +    if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))<br>
> +      return A->getValue();<br>
> +    return "";<br>
> +<br>
>    case llvm::Triple::ppc:<br>
>    case llvm::Triple::ppc64:<br>
>    case llvm::Triple::ppc64le: {<br>
> @@ -2826,8 +2832,14 @@ void Clang::ConstructJob(Compilation &C,<br>
>        getToolChain().getTriple().isWindowsCygwinEnvironment();<br>
>    bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();<br>
><br>
> -  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");<br>
> +  // Check number of inputs for sanity. We need at least one input.<br>
> +  assert(Inputs.size() >= 1 && "Must have at least one input.");<br>
>    const InputInfo &Input = Inputs[0];<br>
> +  // CUDA compilation may have multiple inputs (source file + results of<br>
> +  // device-side compilations). All other jobs are expected to have exactly one<br>
> +  // input.<br>
> +  bool IsCuda = types::isCuda(Input.getType());<br>
> +  assert((IsCuda || Inputs.size() == 1) && "Unable to handle multiple inputs.");<br>
><br>
>    // Invoke ourselves in -cc1 mode.<br>
>    //<br>
> @@ -4812,14 +4824,12 @@ void Clang::ConstructJob(Compilation &C,<br>
>      assert(Output.isNothing() && "Invalid output.");<br>
>    }<br>
><br>
> -  for (const auto &II : Inputs) {<br>
> -    addDashXForInput(Args, II, CmdArgs);<br>
> +  addDashXForInput(Args, Input, CmdArgs);<br>
><br>
> -    if (II.isFilename())<br>
> -      CmdArgs.push_back(II.getFilename());<br>
> -    else<br>
> -      II.getInputArg().renderAsInput(Args, CmdArgs);<br>
> -  }<br>
> +  if (Input.isFilename())<br>
> +    CmdArgs.push_back(Input.getFilename());<br>
> +  else<br>
> +    Input.getInputArg().renderAsInput(Args, CmdArgs);<br>
><br>
>    Args.AddAllArgs(CmdArgs, options::OPT_undef);<br>
><br>
> @@ -4857,6 +4867,16 @@ void Clang::ConstructJob(Compilation &C,<br>
>      CmdArgs.push_back(SplitDwarfOut);<br>
>    }<br>
><br>
> +  // Host-side cuda compilation receives device-side outputs as Inputs[1...].<br>
> +  // Include them with -fcuda-include-gpubinary.<br>
> +  if (IsCuda && Inputs.size() > 1)<br>
> +    for (InputInfoList::const_iterator it = std::next(Inputs.begin()),<br>
> +                                       ie = Inputs.end();<br>
> +         it != ie; ++it) {<br>
> +      CmdArgs.push_back("-fcuda-include-gpubinary");<br>
> +      CmdArgs.push_back(it->getFilename());<br>
> +    }<br>
> +<br>
>    // Finally add the compile command to the compilation.<br>
>    if (Args.hasArg(options::OPT__SLASH_fallback) &&<br>
>        Output.getType() == types::TY_Object &&<br>
><br>
> Modified: cfe/trunk/lib/Driver/Types.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Driver_Types.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=9AMjh1hCYVutEDGvGsrfutLiN-liIV6zlcJutmRqmWk&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Types.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Driver/Types.cpp (original)<br>
> +++ cfe/trunk/lib/Driver/Types.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -86,6 +86,7 @@ bool types::isAcceptedByClang(ID Id) {<br>
>    case TY_C: case TY_PP_C:<br>
>    case TY_CL:<br>
>    case TY_CUDA: case TY_PP_CUDA:<br>
> +  case TY_CUDA_DEVICE:<br>
>    case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:<br>
>    case TY_CXX: case TY_PP_CXX:<br>
>    case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:<br>
> @@ -122,7 +123,19 @@ bool types::isCXX(ID Id) {<br>
>    case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:<br>
>    case TY_CXXHeader: case TY_PP_CXXHeader:<br>
>    case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:<br>
> -  case TY_CUDA: case TY_PP_CUDA:<br>
> +  case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:<br>
> +    return true;<br>
> +  }<br>
> +}<br>
> +<br>
> +bool types::isCuda(ID Id) {<br>
> +  switch (Id) {<br>
> +  default:<br>
> +    return false;<br>
> +<br>
> +  case TY_CUDA:<br>
> +  case TY_PP_CUDA:<br>
> +  case TY_CUDA_DEVICE:<br>
>      return true;<br>
>    }<br>
>  }<br>
> @@ -206,10 +219,12 @@ void types::getCompilationPhases(ID Id,<br>
>          P.push_back(phases::Compile);<br>
>          P.push_back(phases::Backend);<br>
>        }<br>
> -      P.push_back(phases::Assemble);<br>
> +      if (Id != TY_CUDA_DEVICE)<br>
> +        P.push_back(phases::Assemble);<br>
>      }<br>
>    }<br>
> -  if (!onlyPrecompileType(Id)) {<br>
> +<br>
> +  if (!onlyPrecompileType(Id) && Id != TY_CUDA_DEVICE) {<br>
>      P.push_back(phases::Link);<br>
>    }<br>
>    assert(0 < P.size() && "Not enough phases in list");<br>
><br>
> Modified: cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Frontend_CreateInvocationFromCommandLine.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=wg3t3SrkNqbaYgAoHetHahNjzYN60KNOwlZ5uzG-8HM&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp (original)<br>
> +++ cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -15,6 +15,7 @@<br>
>  #include "clang/Basic/DiagnosticOptions.h"<br>
>  #include "clang/Driver/Compilation.h"<br>
>  #include "clang/Driver/Driver.h"<br>
> +#include "clang/Driver/Action.h"<br>
>  #include "clang/Driver/Options.h"<br>
>  #include "clang/Driver/Tool.h"<br>
>  #include "clang/Frontend/CompilerInstance.h"<br>
> @@ -61,9 +62,25 @@ clang::createInvocationFromCommandLine(A<br>
>    }<br>
><br>
>    // We expect to get back exactly one command job, if we didn't something<br>
> -  // failed.<br>
> +  // failed. CUDA compilation is an exception as it creates multiple jobs. If<br>
> +  // that's the case, we proceed with the first job. If caller needs particular<br>
> +  // CUDA job, it should be controlled via --cuda-{host|device}-only option<br>
> +  // passed to the driver.<br>
>    const driver::JobList &Jobs = C->getJobs();<br>
> -  if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {<br>
> +  bool CudaCompilation = false;<br>
> +  if (Jobs.size() > 1) {<br>
> +    for (auto &A : C->getActions()){<br>
> +      // On MacOSX real actions may end up being wrapped in BindArchAction<br>
> +      if (isa<driver::BindArchAction>(A))<br>
> +        A = *A->begin();<br>
> +      if (isa<driver::CudaDeviceAction>(A)) {<br>
> +        CudaCompilation = true;<br>
> +        break;<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +  if (Jobs.size() == 0 || !isa<driver::Command>(*Jobs.begin()) ||<br>
> +      (Jobs.size() > 1 && !CudaCompilation)) {<br>
>      SmallString<256> Msg;<br>
>      llvm::raw_svector_ostream OS(Msg);<br>
>      Jobs.Print(OS, "; ", true);<br>
><br>
> Added: cfe/trunk/test/Driver/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__cuda-2Doptions.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=JETtyv_A1yjmTD_KmoFDoStKOHa9fmHDH6OI0wsJLU8&e=" rel="noreferrer" target="_blank">cuda-options.cu</a><br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_Driver_cuda-2Doptions.cu-3Frev-3D242085-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=FylP1lgV5yOJ3MWPvEkQxpMnX6K1fmsutyfjY1CPFVg&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cuda-options.cu?rev=242085&view=auto</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/Driver/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__cuda-2Doptions.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=JETtyv_A1yjmTD_KmoFDoStKOHa9fmHDH6OI0wsJLU8&e=" rel="noreferrer" target="_blank">cuda-options.cu</a> (added)<br>
> +++ cfe/trunk/test/Driver/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__cuda-2Doptions.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=JETtyv_A1yjmTD_KmoFDoStKOHa9fmHDH6OI0wsJLU8&e=" rel="noreferrer" target="_blank">cuda-options.cu</a> Mon Jul 13 18:27:56 2015<br>
> @@ -0,0 +1,109 @@<br>
> +// Tests CUDA compilation pipeline construction in Driver.<br>
> +// REQUIRES: clang-driver<br>
> +<br>
> +// Simple compilation case:<br>
> +// RUN: %clang -### -c %s 2>&1 \<br>
> +// Compile device-side to PTX assembly and make sure we use it on the host side.<br>
> +// RUN:   | FileCheck -check-prefix CUDA-D1 \<br>
> +// Then compile host side and incorporate device code.<br>
> +// RUN:   -check-prefix CUDA-H -check-prefix CUDA-H-I1 \<br>
> +// Make sure we don't link anything.<br>
> +// RUN:   -check-prefix CUDA-NL %s<br>
> +<br>
> +// Typical compilation + link case:<br>
> +// RUN: %clang -### %s 2>&1 \<br>
> +// Compile device-side to PTX assembly and make sure we use it on the host side<br>
> +// RUN:   | FileCheck -check-prefix CUDA-D1 \<br>
> +// Then compile host side and incorporate device code.<br>
> +// RUN:   -check-prefix CUDA-H -check-prefix CUDA-H-I1 \<br>
> +// Then link things.<br>
> +// RUN:   -check-prefix CUDA-L %s<br>
> +<br>
> +// Verify that -cuda-no-device disables device-side compilation and linking<br>
> +// RUN: %clang -### --cuda-host-only %s 2>&1 \<br>
> +// Make sure we didn't run device-side compilation.<br>
> +// RUN:   | FileCheck -check-prefix CUDA-ND \<br>
> +// Then compile host side and make sure we don't attempt to incorporate GPU code.<br>
> +// RUN:    -check-prefix CUDA-H -check-prefix CUDA-H-NI \<br>
> +// Make sure we don't link anything.<br>
> +// RUN:    -check-prefix CUDA-NL %s<br>
> +<br>
> +// Verify that -cuda-no-host disables host-side compilation and linking<br>
> +// RUN: %clang -### --cuda-device-only %s 2>&1 \<br>
> +// Compile device-side to PTX assembly<br>
> +// RUN:   | FileCheck -check-prefix CUDA-D1 \<br>
> +// Make sure there are no host cmpilation or linking.<br>
> +// RUN:   -check-prefix CUDA-NH -check-prefix CUDA-NL %s<br>
> +<br>
> +// Verify that with -S we compile host and device sides to assembly<br>
> +// and incorporate device code on the host side.<br>
> +// RUN: %clang -### -S -c %s 2>&1 \<br>
> +// Compile device-side to PTX assembly<br>
> +// RUN:   | FileCheck -check-prefix CUDA-D1 \<br>
> +// Then compile host side and incorporate GPU code.<br>
> +// RUN:  -check-prefix CUDA-H -check-prefix CUDA-H-I1 \<br>
> +// Make sure we don't link anything.<br>
> +// RUN:  -check-prefix CUDA-NL %s<br>
> +<br>
> +// Verify that --cuda-gpu-arch option passes correct GPU<br>
> +// archtecture info to device compilation.<br>
> +// RUN: %clang -### --cuda-gpu-arch=sm_35 -c %s 2>&1 \<br>
> +// Compile device-side to PTX assembly.<br>
> +// RUN:   | FileCheck -check-prefix CUDA-D1 -check-prefix CUDA-D1-SM35 \<br>
> +// Then compile host side and incorporate GPU code.<br>
> +// RUN:   -check-prefix CUDA-H -check-prefix CUDA-H-I1 \<br>
> +// Make sure we don't link anything.<br>
> +// RUN:   -check-prefix CUDA-NL %s<br>
> +<br>
> +// Verify that there is device-side compilation per --cuda-gpu-arch args<br>
> +// and that all results are included on the host side.<br>
> +// RUN: %clang -### --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 -c %s 2>&1 \<br>
> +// Compile both device-sides to PTX assembly<br>
> +// RUN:   | FileCheck \<br>
> +// RUN: -check-prefix CUDA-D1 -check-prefix CUDA-D1-SM35 \<br>
> +// RUN: -check-prefix CUDA-D2 -check-prefix CUDA-D2-SM30 \<br>
> +// Then compile host side and incorporate both device-side outputs<br>
> +// RUN:   -check-prefix CUDA-H -check-prefix CUDA-H-I1 -check-prefix CUDA-H-I2 \<br>
> +// Make sure we don't link anything.<br>
> +// RUN:   -check-prefix CUDA-NL %s<br>
> +<br>
> +// Match device-side compilation<br>
> +// CUDA-D1: "-cc1" "-triple" "nvptx{{(64)?}}-nvidia-cuda"<br>
> +// CUDA-D1-SAME: "-fcuda-is-device"<br>
> +// CUDA-D1-SM35-SAME: "-target-cpu" "sm_35"<br>
> +// CUDA-D1-SAME: "-o" "[[GPUBINARY1:[^"]*]]"<br>
> +// CUDA-D1-SAME: "-x" "cuda"<br>
> +<br>
> +// Match anothe device-side compilation<br>
> +// CUDA-D2: "-cc1" "-triple" "nvptx{{(64)?}}-nvidia-cuda"<br>
> +// CUDA-D2-SAME: "-fcuda-is-device"<br>
> +// CUDA-D2-SM30-SAME: "-target-cpu" "sm_30"<br>
> +// CUDA-D2-SAME: "-o" "[[GPUBINARY2:[^"]*]]"<br>
> +// CUDA-D2-SAME: "-x" "cuda"<br>
> +<br>
> +// Match no device-side compilation<br>
> +// CUDA-ND-NOT: "-cc1" "-triple" "nvptx{{64?}}-nvidia-cuda"<br>
> +// CUDA-ND-SAME-NOT: "-fcuda-is-device"<br>
> +<br>
> +// Match host-side compilation<br>
> +// CUDA-H: "-cc1" "-triple"<br>
> +// CUDA-H-SAME-NOT: "nvptx{{64?}}-nvidia-cuda"<br>
> +// CUDA-H-SAME-NOT: "-fcuda-is-device"<br>
> +// CUDA-H-SAME: "-o" "[[HOSTOBJ:[^"]*]]"<br>
> +// CUDA-H-SAME: "-x" "cuda"<br>
> +// CUDA-H-I1-SAME: "-fcuda-include-gpubinary" "[[GPUBINARY1]]"<br>
> +// CUDA-H-I2-SAME: "-fcuda-include-gpubinary" "[[GPUBINARY2]]"<br>
> +<br>
> +// Match no GPU code inclusion.<br>
> +// CUDA-H-NI-NOT: "-fcuda-include-gpubinary"<br>
> +<br>
> +// Match no CUDA compilation<br>
> +// CUDA-NH-NOT: "-cc1" "-triple"<br>
> +// CUDA-NH-SAME-NOT: "-x" "cuda"<br>
> +<br>
> +// Match linker<br>
> +// CUDA-L: "{{.*}}ld{{(.exe)?}}"<br>
> +// CUDA-L-SAME: "[[HOSTOBJ]]"<br>
> +<br>
> +// Match no linker<br>
> +// CUDA-NL-NOT: "{{.*}}ld{{(.exe)?}}"<br>
><br>
> Modified: cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__attributes-2Dcuda.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=mTykXFMrswBOTJhzDBRffZ1C-BvcUHI5JLq6wIBSfbg&e=" rel="noreferrer" target="_blank">attributes-cuda.cu</a><br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_Index_attributes-2Dcuda.cu-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=9lgGnxaMaTne6u5dnj6LAjTqikN03kyo67ajgqFhssk&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/attributes-cuda.cu?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__attributes-2Dcuda.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=mTykXFMrswBOTJhzDBRffZ1C-BvcUHI5JLq6wIBSfbg&e=" rel="noreferrer" target="_blank">attributes-cuda.cu</a> (original)<br>
> +++ cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__attributes-2Dcuda.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=mTykXFMrswBOTJhzDBRffZ1C-BvcUHI5JLq6wIBSfbg&e=" rel="noreferrer" target="_blank">attributes-cuda.cu</a> Mon Jul 13 18:27:56 2015<br>
> @@ -1,4 +1,6 @@<br>
>  // RUN: c-index-test -test-load-source all -x cuda %s | FileCheck %s<br>
> +// RUN: c-index-test -test-load-source all -x cuda --cuda-host-only %s | FileCheck %s<br>
> +// RUN: c-index-test -test-load-source all -x cuda --cuda-device-only %s | FileCheck %s<br>
><br>
>  __attribute__((device)) void f_device();<br>
>  __attribute__((global)) void f_global();<br>
> @@ -6,13 +8,13 @@ __attribute__((constant)) int* g_constan<br>
>  __attribute__((shared)) float *g_shared;<br>
>  __attribute__((host)) void f_host();<br>
><br>
> -// CHECK:       attributes-cuda.cu:3:30: FunctionDecl=f_device:3:30<br>
> -// CHECK-NEXT:  attributes-cuda.cu:3:16: attribute(device)<br>
> -// CHECK:       attributes-cuda.cu:4:30: FunctionDecl=f_global:4:30<br>
> -// CHECK-NEXT:  attributes-cuda.cu:4:16: attribute(global)<br>
> -// CHECK:       attributes-cuda.cu:5:32: VarDecl=g_constant:5:32 (Definition)<br>
> -// CHECK-NEXT:  attributes-cuda.cu:5:16: attribute(constant)<br>
> -// CHECK:       attributes-cuda.cu:6:32: VarDecl=g_shared:6:32 (Definition)<br>
> -// CHECK-NEXT:  attributes-cuda.cu:6:16: attribute(shared)<br>
> -// CHECK:       attributes-cuda.cu:7:28: FunctionDecl=f_host:7:28<br>
> -// CHECK-NEXT:  attributes-cuda.cu:7:16: attribute(host)<br>
> +// CHECK:       attributes-cuda.cu:5:30: FunctionDecl=f_device:5:30<br>
> +// CHECK-NEXT:  attributes-cuda.cu:5:16: attribute(device)<br>
> +// CHECK:       attributes-cuda.cu:6:30: FunctionDecl=f_global:6:30<br>
> +// CHECK-NEXT:  attributes-cuda.cu:6:16: attribute(global)<br>
> +// CHECK:       attributes-cuda.cu:7:32: VarDecl=g_constant:7:32 (Definition)<br>
> +// CHECK-NEXT:  attributes-cuda.cu:7:16: attribute(constant)<br>
> +// CHECK:       attributes-cuda.cu:8:32: VarDecl=g_shared:8:32 (Definition)<br>
> +// CHECK-NEXT:  attributes-cuda.cu:8:16: attribute(shared)<br>
> +// CHECK:       attributes-cuda.cu:9:28: FunctionDecl=f_host:9:28<br>
> +// CHECK-NEXT:  attributes-cuda.cu:9:16: attribute(host)<br>
><br>
> Added: cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__index-2Dfile.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=Z26JivvnfsF4tloeePDLQLHxsFQrEclL-D6_alidUsQ&e=" rel="noreferrer" target="_blank">index-file.cu</a><br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_Index_index-2Dfile.cu-3Frev-3D242085-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=KT-XgqFAI7Vl93vVOFFXhEywRf8qjxjSFX-IW8oVbs0&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/index-file.cu?rev=242085&view=auto</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__index-2Dfile.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=Z26JivvnfsF4tloeePDLQLHxsFQrEclL-D6_alidUsQ&e=" rel="noreferrer" target="_blank">index-file.cu</a> (added)<br>
> +++ cfe/trunk/test/Index/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__index-2Dfile.cu&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=Z26JivvnfsF4tloeePDLQLHxsFQrEclL-D6_alidUsQ&e=" rel="noreferrer" target="_blank">index-file.cu</a> Mon Jul 13 18:27:56 2015<br>
> @@ -0,0 +1,9 @@<br>
> +// Make sure we can process CUDA file even if driver creates multiple jobs<br>
> +// RUN: c-index-test -test-load-source all %s | FileCheck %s -check-prefix=CHECK-ANY<br>
> +// Make sure we process correct side of cuda compilation<br>
> +// RUN: c-index-test -test-load-source all --cuda-host-only %s | FileCheck %s -check-prefix=CHECK-HOST<br>
> +// RUN: c-index-test -test-load-source all --cuda-device-only %s | FileCheck %s -check-prefix=CHECK-DEVICE<br>
> +<br>
> +// CHECK-ANY: macro definition=__cplusplus<br>
> +// CHECK-HOST-NOT: macro definition=__CUDA_ARCH__<br>
> +// CHECK-DEVICE: macro definition=__CUDA_ARCH__<br>
><br>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_tools_libclang_CIndex.cpp-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=kEIx9idn_Ke-DCJSORFu3jCYCUWk4PlZRvVP-ltWRl8&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)<br>
> +++ cfe/trunk/tools/libclang/CIndex.cpp Mon Jul 13 18:27:56 2015<br>
> @@ -3102,6 +3102,12 @@ static void clang_parseTranslationUnit_I<br>
>        /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies,<br>
>        /*UserFilesAreVolatile=*/true, ForSerialization, &ErrUnit));<br>
><br>
> +  // Early failures in LoadFromCommandLine may return with ErrUnit unset.<br>
> +  if (!Unit && !ErrUnit) {<br>
> +    PTUI->result = CXError_ASTReadError;<br>
> +    return;<br>
> +  }<br>
> +<br>
>    if (NumErrors != Diags->getClient()->getNumErrors()) {<br>
>      // Make sure to check that 'Unit' is non-NULL.<br>
>      if (CXXIdx->getDisplayDiagnostics())<br>
><br>
> Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_unittests_ASTMatchers_ASTMatchersTest.h-3Frev-3D242085-26r1-3D242084-26r2-3D242085-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=I75miQAMK63tX32WH6iO2jq6asYQmsOGeyoe-6dPuuw&s=0VXYPHEwSel_CTLnuvdLSFw4gVs5G-ER5qz_NzOkvFM&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h?rev=242085&r1=242084&r2=242085&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h (original)<br>
> +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h Mon Jul 13 18:27:56 2015<br>
> @@ -164,6 +164,7 @@ testing::AssertionResult matchesConditio<br>
>    std::vector<std::string> Args;<br>
>    Args.push_back("-xcuda");<br>
>    Args.push_back("-fno-ms-extensions");<br>
> +  Args.push_back("--cuda-host-only");<br>
>    Args.push_back(CompileArg);<br>
>    if (!runToolOnCodeWithArgs(Factory->create(),<br>
>                               CudaHeader + Code, Args)) {<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div></div>