head	1.1;
branch	1.1.1;
access;
symbols
	perseant-exfatfs-base-20261102:1.1.1.10
	netbsd-11-1-RELEASE:1.1.1.10
	netbsd-10-2-RELEASE:1.1.1.10
	netbsd-9-5-RELEASE:1.1.1.9
	netbsd-11-0-RELEASE:1.1.1.10
	netbsd-11-0-RC7:1.1.1.10
	netbsd-11-0-RC6:1.1.1.10
	netbsd-11-0-RC5:1.1.1.10
	netbsd-11-0-RC4:1.1.1.10
	netbsd-11-0-RC3:1.1.1.10
	netbsd-11-0-RC2:1.1.1.10
	netbsd-11-0-RC1:1.1.1.10
	perseant-exfatfs-base-20250801:1.1.1.10
	netbsd-11:1.1.1.10.0.10
	netbsd-11-base:1.1.1.10
	netbsd-10-1-RELEASE:1.1.1.10
	perseant-exfatfs-base-20240630:1.1.1.10
	perseant-exfatfs:1.1.1.10.0.8
	perseant-exfatfs-base:1.1.1.10
	netbsd-8-3-RELEASE:1.1.1.7
	netbsd-9-4-RELEASE:1.1.1.9
	netbsd-10-0-RELEASE:1.1.1.10
	netbsd-10-0-RC6:1.1.1.10
	netbsd-10-0-RC5:1.1.1.10
	netbsd-10-0-RC4:1.1.1.10
	netbsd-10-0-RC3:1.1.1.10
	netbsd-10-0-RC2:1.1.1.10
	netbsd-10-0-RC1:1.1.1.10
	netbsd-10:1.1.1.10.0.6
	netbsd-10-base:1.1.1.10
	netbsd-9-3-RELEASE:1.1.1.9
	cjep_sun2x:1.1.1.10.0.4
	cjep_sun2x-base:1.1.1.10
	cjep_staticlib_x-base1:1.1.1.10
	netbsd-9-2-RELEASE:1.1.1.9
	cjep_staticlib_x:1.1.1.10.0.2
	cjep_staticlib_x-base:1.1.1.10
	netbsd-9-1-RELEASE:1.1.1.9
	phil-wifi-20200421:1.1.1.10
	phil-wifi-20200411:1.1.1.10
	phil-wifi-20200406:1.1.1.10
	netbsd-8-2-RELEASE:1.1.1.7
	netbsd-9-0-RELEASE:1.1.1.9
	netbsd-9-0-RC2:1.1.1.9
	netbsd-9-0-RC1:1.1.1.9
	netbsd-9:1.1.1.9.0.2
	netbsd-9-base:1.1.1.9
	phil-wifi-20190609:1.1.1.9
	netbsd-8-1-RELEASE:1.1.1.7
	netbsd-8-1-RC1:1.1.1.7
	pgoyette-compat-merge-20190127:1.1.1.8.2.1
	pgoyette-compat-20190127:1.1.1.9
	pgoyette-compat-20190118:1.1.1.9
	pgoyette-compat-1226:1.1.1.9
	pgoyette-compat-1126:1.1.1.9
	pgoyette-compat-1020:1.1.1.9
	pgoyette-compat-0930:1.1.1.9
	pgoyette-compat-0906:1.1.1.9
	netbsd-7-2-RELEASE:1.1.1.4.2.1
	pgoyette-compat-0728:1.1.1.9
	clang-337282:1.1.1.9
	netbsd-8-0-RELEASE:1.1.1.7
	phil-wifi:1.1.1.8.0.4
	phil-wifi-base:1.1.1.8
	pgoyette-compat-0625:1.1.1.8
	netbsd-8-0-RC2:1.1.1.7
	pgoyette-compat-0521:1.1.1.8
	pgoyette-compat-0502:1.1.1.8
	pgoyette-compat-0422:1.1.1.8
	netbsd-8-0-RC1:1.1.1.7
	pgoyette-compat-0415:1.1.1.8
	pgoyette-compat-0407:1.1.1.8
	pgoyette-compat-0330:1.1.1.8
	pgoyette-compat-0322:1.1.1.8
	pgoyette-compat-0315:1.1.1.8
	netbsd-7-1-2-RELEASE:1.1.1.4.2.1
	pgoyette-compat:1.1.1.8.0.2
	pgoyette-compat-base:1.1.1.8
	netbsd-7-1-1-RELEASE:1.1.1.4.2.1
	clang-319952:1.1.1.8
	matt-nb8-mediatek:1.1.1.7.0.10
	matt-nb8-mediatek-base:1.1.1.7
	clang-309604:1.1.1.8
	perseant-stdc-iso10646:1.1.1.7.0.8
	perseant-stdc-iso10646-base:1.1.1.7
	netbsd-8:1.1.1.7.0.6
	netbsd-8-base:1.1.1.7
	prg-localcount2-base3:1.1.1.7
	prg-localcount2-base2:1.1.1.7
	prg-localcount2-base1:1.1.1.7
	prg-localcount2:1.1.1.7.0.4
	prg-localcount2-base:1.1.1.7
	pgoyette-localcount-20170426:1.1.1.7
	bouyer-socketcan-base1:1.1.1.7
	pgoyette-localcount-20170320:1.1.1.7
	netbsd-7-1:1.1.1.4.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.4.2.1
	netbsd-7-1-RC2:1.1.1.4.2.1
	clang-294123:1.1.1.7
	netbsd-7-nhusb-base-20170116:1.1.1.4.2.1
	bouyer-socketcan:1.1.1.7.0.2
	bouyer-socketcan-base:1.1.1.7
	clang-291444:1.1.1.7
	pgoyette-localcount-20170107:1.1.1.6
	netbsd-7-1-RC1:1.1.1.4.2.1
	pgoyette-localcount-20161104:1.1.1.6
	netbsd-7-0-2-RELEASE:1.1.1.4.2.1
	localcount-20160914:1.1.1.6
	netbsd-7-nhusb:1.1.1.4.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.4.2.1
	clang-280599:1.1.1.6
	pgoyette-localcount-20160806:1.1.1.6
	pgoyette-localcount-20160726:1.1.1.6
	pgoyette-localcount:1.1.1.6.0.2
	pgoyette-localcount-base:1.1.1.6
	netbsd-7-0-1-RELEASE:1.1.1.4.2.1
	clang-261930:1.1.1.6
	netbsd-7-0:1.1.1.4.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.4.2.1
	netbsd-7-0-RC3:1.1.1.4.2.1
	netbsd-7-0-RC2:1.1.1.4.2.1
	netbsd-7-0-RC1:1.1.1.4.2.1
	clang-237755:1.1.1.5
	clang-232565:1.1.1.5
	clang-227398:1.1.1.5
	tls-maxphys-base:1.1.1.4
	tls-maxphys:1.1.1.4.0.4
	netbsd-7:1.1.1.4.0.2
	netbsd-7-base:1.1.1.4
	clang-215315:1.1.1.4
	clang-209886:1.1.1.3
	yamt-pagecache:1.1.1.2.0.4
	yamt-pagecache-base9:1.1.1.2
	tls-earlyentropy:1.1.1.2.0.2
	tls-earlyentropy-base:1.1.1.3
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.2
	riastradh-drm2-base3:1.1.1.2
	clang-202566:1.1.1.2
	clang-201163:1.1.1.1
	clang-199312:1.1.1.1
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.52;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.52;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.03.04.19.54.54;	author joerg;	state Exp;
branches
	1.1.1.2.2.1
	1.1.1.2.4.1;
next	1.1.1.3;
commitid	29z1hJonZISIXprx;

1.1.1.3
date	2014.05.30.18.14.41;	author joerg;	state Exp;
branches;
next	1.1.1.4;
commitid	8q0kdlBlCn09GACx;

1.1.1.4
date	2014.08.10.17.08.34;	author joerg;	state Exp;
branches
	1.1.1.4.2.1
	1.1.1.4.4.1;
next	1.1.1.5;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.5
date	2015.01.29.19.57.30;	author joerg;	state Exp;
branches;
next	1.1.1.6;
commitid	mlISSizlPKvepX7y;

1.1.1.6
date	2016.02.27.22.12.04;	author joerg;	state Exp;
branches
	1.1.1.6.2.1;
next	1.1.1.7;
commitid	tIimz3oDlh1NpBWy;

1.1.1.7
date	2017.01.11.10.33.40;	author joerg;	state Exp;
branches;
next	1.1.1.8;
commitid	CNnUNfII1jgNmxBz;

1.1.1.8
date	2017.08.01.19.34.59;	author joerg;	state Exp;
branches
	1.1.1.8.2.1
	1.1.1.8.4.1;
next	1.1.1.9;
commitid	pMuDy65V0VicSx1A;

1.1.1.9
date	2018.07.17.18.31.13;	author joerg;	state Exp;
branches;
next	1.1.1.10;
commitid	wDzL46ALjrCZgwKA;

1.1.1.10
date	2019.11.13.22.19.22;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.2.2.1
date	2014.08.10.07.08.08;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.2.4.1
date	2014.03.04.19.54.54;	author yamt;	state dead;
branches;
next	1.1.1.2.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.2.4.2
date	2014.05.22.16.18.27;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.4.2.1
date	2015.06.04.20.04.28;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.4.4.1
date	2014.08.10.17.08.34;	author tls;	state dead;
branches;
next	1.1.1.4.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.4.4.2
date	2014.08.19.23.47.27;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.6.2.1
date	2017.03.20.06.52.37;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.8.2.1
date	2018.07.28.04.33.18;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.8.4.1
date	2019.06.10.21.45.22;	author christos;	state Exp;
branches;
next	1.1.1.8.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.8.4.2
date	2020.04.13.07.46.33;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- Job.cpp - Command to Execute -------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Job.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
using namespace clang::driver;
using llvm::raw_ostream;
using llvm::StringRef;

Job::~Job() {}

Command::Command(const Action &_Source, const Tool &_Creator,
                 const char *_Executable,
                 const ArgStringList &_Arguments)
    : Job(CommandClass), Source(_Source), Creator(_Creator),
      Executable(_Executable), Arguments(_Arguments) {}

static int skipArgs(const char *Flag) {
  // These flags are all of the form -Flag <Arg> and are treated as two
  // arguments.  Therefore, we need to skip the flag and the next argument.
  bool Res = llvm::StringSwitch<bool>(Flag)
    .Cases("-I", "-MF", "-MT", "-MQ", true)
    .Cases("-o", "-coverage-file", "-dependency-file", true)
    .Cases("-fdebug-compilation-dir", "-idirafter", true)
    .Cases("-include", "-include-pch", "-internal-isystem", true)
    .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
    .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true)
    .Cases("-resource-dir", "-serialize-diagnostic-file", true)
    .Case("-dwarf-debug-flags", true)
    .Default(false);

  // Match found.
  if (Res)
    return 2;

  // The remaining flags are treated as a single argument.

  // These flags are all of the form -Flag and have no second argument.
  Res = llvm::StringSwitch<bool>(Flag)
    .Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
    .Case("-MMD", true)
    .Default(false);

  // Match found.
  if (Res)
    return 1;

  // These flags are treated as a single argument (e.g., -F<Dir>).
  StringRef FlagRef(Flag);
  if (FlagRef.startswith("-F") || FlagRef.startswith("-I"))
    return 1;

  return 0;
}

static bool quoteNextArg(const char *flag) {
  return llvm::StringSwitch<bool>(flag)
    .Case("-D", true)
    .Default(false);
}

static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) {
  const bool Escape = std::strpbrk(Arg, "\"\\$");

  if (!Quote && !Escape) {
    OS << Arg;
    return;
  }

  // Quote and escape. This isn't really complete, but good enough.
  OS << '"';
  while (const char c = *Arg++) {
    if (c == '"' || c == '\\' || c == '$')
      OS << '\\';
    OS << c;
  }
  OS << '"';
}

void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
                    bool CrashReport) const {
  OS << " \"" << Executable << '"';

  for (size_t i = 0, e = Arguments.size(); i < e; ++i) {
    const char *const Arg = Arguments[i];

    if (CrashReport) {
      if (int Skip = skipArgs(Arg)) {
        i += Skip - 1;
        continue;
      }
    }

    OS << ' ';
    PrintArg(OS, Arg, Quote);

    if (CrashReport && quoteNextArg(Arg) && i + 1 < e) {
      OS << ' ';
      PrintArg(OS, Arguments[++i], true);
    }
  }
  OS << Terminator;
}

int Command::Execute(const StringRef **Redirects, std::string *ErrMsg,
                     bool *ExecutionFailed) const {
  SmallVector<const char*, 128> Argv;
  Argv.push_back(Executable);
  for (size_t i = 0, e = Arguments.size(); i != e; ++i)
    Argv.push_back(Arguments[i]);
  Argv.push_back(0);

  return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ 0,
                                   Redirects, /*secondsToWait*/ 0,
                                   /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}

FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
                                 const char *Executable_,
                                 const ArgStringList &Arguments_,
                                 Command *Fallback_)
    : Command(Source_, Creator_, Executable_, Arguments_), Fallback(Fallback_) {
}

void FallbackCommand::Print(raw_ostream &OS, const char *Terminator,
                            bool Quote, bool CrashReport) const {
  Command::Print(OS, "", Quote, CrashReport);
  OS << " ||";
  Fallback->Print(OS, Terminator, Quote, CrashReport);
}

static bool ShouldFallback(int ExitCode) {
  // FIXME: We really just want to fall back for internal errors, such
  // as when some symbol cannot be mangled, when we should be able to
  // parse something but can't, etc.
  return ExitCode != 0;
}

int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg,
                             bool *ExecutionFailed) const {
  int PrimaryStatus = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
  if (!ShouldFallback(PrimaryStatus))
    return PrimaryStatus;

  // Clear ExecutionFailed and ErrMsg before falling back.
  if (ErrMsg)
    ErrMsg->clear();
  if (ExecutionFailed)
    *ExecutionFailed = false;

  int SecondaryStatus = Fallback->Execute(Redirects, ErrMsg, ExecutionFailed);
  return SecondaryStatus;
}

JobList::JobList() : Job(JobListClass) {}

JobList::~JobList() {
  for (iterator it = begin(), ie = end(); it != ie; ++it)
    delete *it;
}

void JobList::Print(raw_ostream &OS, const char *Terminator, bool Quote,
                    bool CrashReport) const {
  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
    (*it)->Print(OS, Terminator, Quote, CrashReport);
}

void JobList::clear() {
  DeleteContainerPointers(Jobs);
}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import Clang 3.5svn r202566.
@
text
@a9 2
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
a10 2
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
a161 3
  const Driver &D = getCreator().getToolChain().getDriver();
  D.Diag(diag::warn_drv_invoking_fallback) << Fallback->getExecutable();

@


1.1.1.2.2.1
log
@Rebase.
@
text
@d65 1
a65 2
  if (FlagRef.startswith("-F") || FlagRef.startswith("-I") ||
      FlagRef.startswith("-fmodules-cache-path="))
d126 1
a126 1
  Argv.push_back(nullptr);
d128 1
a128 1
  return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
@


1.1.1.3
log
@Import Clang 3.5svn r209886.
@
text
@d65 1
a65 2
  if (FlagRef.startswith("-F") || FlagRef.startswith("-I") ||
      FlagRef.startswith("-fmodules-cache-path="))
d126 1
a126 1
  Argv.push_back(nullptr);
d128 1
a128 1
  return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
@


1.1.1.4
log
@Import clang 3.6svn r215315.
@
text
@d44 1
a44 1
    .Cases("-dwarf-debug-flags", "-ivfsoverlay", true)
d98 1
a98 3
  // Always quote the exe.
  OS << ' ';
  PrintArg(OS, Executable, /*Quote=*/true);
@


1.1.1.4.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@a14 1
#include "llvm/ADT/ArrayRef.h"
a16 1
#include "llvm/ADT/StringSet.h"
a23 1
using llvm::ArrayRef;
d31 1
a31 2
      Executable(_Executable), Arguments(_Arguments),
      ResponseFile(nullptr) {}
d72 6
a95 53
void Command::writeResponseFile(raw_ostream &OS) const {
  // In a file list, we only write the set of inputs to the response file
  if (Creator.getResponseFilesSupport() == Tool::RF_FileList) {
    for (const char *Arg : InputFileList) {
      OS << Arg << '\n';
    }
    return;
  }

  // In regular response files, we send all arguments to the response file
  for (const char *Arg : Arguments) {
    OS << '"';

    for (; *Arg != '\0'; Arg++) {
      if (*Arg == '\"' || *Arg == '\\') {
        OS << '\\';
      }
      OS << *Arg;
    }

    OS << "\" ";
  }
}

void Command::buildArgvForResponseFile(
    llvm::SmallVectorImpl<const char *> &Out) const {
  // When not a file list, all arguments are sent to the response file.
  // This leaves us to set the argv to a single parameter, requesting the tool
  // to read the response file.
  if (Creator.getResponseFilesSupport() != Tool::RF_FileList) {
    Out.push_back(Executable);
    Out.push_back(ResponseFileFlag.c_str());
    return;
  }

  llvm::StringSet<> Inputs;
  for (const char *InputName : InputFileList)
    Inputs.insert(InputName);
  Out.push_back(Executable);
  // In a file list, build args vector ignoring parameters that will go in the
  // response file (elements of the InputFileList vector)
  bool FirstInput = true;
  for (const char *Arg : Arguments) {
    if (Inputs.count(Arg) == 0) {
      Out.push_back(Arg);
    } else if (FirstInput) {
      FirstInput = false;
      Out.push_back(Creator.getResponseFileFlag());
      Out.push_back(ResponseFile);
    }
  }
}

d97 1
a97 1
                    CrashReportInfo *CrashInfo) const {
d102 2
a103 16
  llvm::ArrayRef<const char *> Args = Arguments;
  llvm::SmallVector<const char *, 128> ArgsRespFile;
  if (ResponseFile != nullptr) {
    buildArgvForResponseFile(ArgsRespFile);
    Args = ArrayRef<const char *>(ArgsRespFile).slice(1); // no executable name
  }

  StringRef MainFilename;
  // We'll need the argument to -main-file-name to find the input file name.
  if (CrashInfo)
    for (size_t I = 0, E = Args.size(); I + 1 < E; ++I)
      if (StringRef(Args[I]).equals("-main-file-name"))
        MainFilename = Args[I + 1];

  for (size_t i = 0, e = Args.size(); i < e; ++i) {
    const char *const Arg = Args[i];
d105 1
a105 1
    if (CrashInfo) {
a108 7
      } else if (llvm::sys::path::filename(Arg) == MainFilename &&
                 (i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) {
        // Replace the input file name with the crashinfo's file name.
        OS << ' ';
        StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename);
        PrintArg(OS, ShortName.str().c_str(), Quote);
        continue;
a113 1
  }
d115 4
a118 15
  if (CrashInfo && !CrashInfo->VFSPath.empty()) {
    OS << ' ';
    PrintArg(OS, "-ivfsoverlay", Quote);
    OS << ' ';
    PrintArg(OS, CrashInfo->VFSPath.str().c_str(), Quote);
  }

  if (ResponseFile != nullptr) {
    OS << "\n Arguments passed via response file:\n";
    writeResponseFile(OS);
    // Avoiding duplicated newline terminator, since FileLists are
    // newline-separated.
    if (Creator.getResponseFilesSupport() != Tool::RF_FileList)
      OS << "\n";
    OS << " (end of response file)";
a119 1

a122 6
void Command::setResponseFile(const char *FileName) {
  ResponseFile = FileName;
  ResponseFileFlag = Creator.getResponseFileFlag();
  ResponseFileFlag += FileName;
}

d126 3
a128 21

  if (ResponseFile == nullptr) {
    Argv.push_back(Executable);
    for (size_t i = 0, e = Arguments.size(); i != e; ++i)
      Argv.push_back(Arguments[i]);
    Argv.push_back(nullptr);

    return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
                                     Redirects, /*secondsToWait*/ 0,
                                     /*memoryLimit*/ 0, ErrMsg,
                                     ExecutionFailed);
  }

  // We need to put arguments in a response file (command is too large)
  // Open stream to store the response file contents
  std::string RespContents;
  llvm::raw_string_ostream SS(RespContents);

  // Write file contents and build the Argv vector
  writeResponseFile(SS);
  buildArgvForResponseFile(Argv);
a129 11
  SS.flush();

  // Save the response file in the appropriate encoding
  if (std::error_code EC = writeFileWithEncoding(
          ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
    if (ErrMsg)
      *ErrMsg = EC.message();
    if (ExecutionFailed)
      *ExecutionFailed = true;
    return -1;
  }
d139 3
a141 3
                                 std::unique_ptr<Command> Fallback_)
    : Command(Source_, Creator_, Executable_, Arguments_),
      Fallback(std::move(Fallback_)) {}
d144 2
a145 2
                            bool Quote, CrashReportInfo *CrashInfo) const {
  Command::Print(OS, "", Quote, CrashInfo);
d147 1
a147 1
  Fallback->Print(OS, Terminator, Quote, CrashInfo);
d178 5
d184 3
a186 3
                    CrashReportInfo *CrashInfo) const {
  for (const auto &Job : *this)
    Job.Print(OS, Terminator, Quote, CrashInfo);
d189 3
a191 1
void JobList::clear() { Jobs.clear(); }
@


1.1.1.5
log
@Import Clang 3.6RC1 r227398.
@
text
@a14 1
#include "llvm/ADT/ArrayRef.h"
a16 1
#include "llvm/ADT/StringSet.h"
a23 1
using llvm::ArrayRef;
d31 1
a31 2
      Executable(_Executable), Arguments(_Arguments),
      ResponseFile(nullptr) {}
d72 6
a95 53
void Command::writeResponseFile(raw_ostream &OS) const {
  // In a file list, we only write the set of inputs to the response file
  if (Creator.getResponseFilesSupport() == Tool::RF_FileList) {
    for (const char *Arg : InputFileList) {
      OS << Arg << '\n';
    }
    return;
  }

  // In regular response files, we send all arguments to the response file
  for (const char *Arg : Arguments) {
    OS << '"';

    for (; *Arg != '\0'; Arg++) {
      if (*Arg == '\"' || *Arg == '\\') {
        OS << '\\';
      }
      OS << *Arg;
    }

    OS << "\" ";
  }
}

void Command::buildArgvForResponseFile(
    llvm::SmallVectorImpl<const char *> &Out) const {
  // When not a file list, all arguments are sent to the response file.
  // This leaves us to set the argv to a single parameter, requesting the tool
  // to read the response file.
  if (Creator.getResponseFilesSupport() != Tool::RF_FileList) {
    Out.push_back(Executable);
    Out.push_back(ResponseFileFlag.c_str());
    return;
  }

  llvm::StringSet<> Inputs;
  for (const char *InputName : InputFileList)
    Inputs.insert(InputName);
  Out.push_back(Executable);
  // In a file list, build args vector ignoring parameters that will go in the
  // response file (elements of the InputFileList vector)
  bool FirstInput = true;
  for (const char *Arg : Arguments) {
    if (Inputs.count(Arg) == 0) {
      Out.push_back(Arg);
    } else if (FirstInput) {
      FirstInput = false;
      Out.push_back(Creator.getResponseFileFlag());
      Out.push_back(ResponseFile);
    }
  }
}

d97 1
a97 1
                    CrashReportInfo *CrashInfo) const {
d102 2
a103 16
  llvm::ArrayRef<const char *> Args = Arguments;
  llvm::SmallVector<const char *, 128> ArgsRespFile;
  if (ResponseFile != nullptr) {
    buildArgvForResponseFile(ArgsRespFile);
    Args = ArrayRef<const char *>(ArgsRespFile).slice(1); // no executable name
  }

  StringRef MainFilename;
  // We'll need the argument to -main-file-name to find the input file name.
  if (CrashInfo)
    for (size_t I = 0, E = Args.size(); I + 1 < E; ++I)
      if (StringRef(Args[I]).equals("-main-file-name"))
        MainFilename = Args[I + 1];

  for (size_t i = 0, e = Args.size(); i < e; ++i) {
    const char *const Arg = Args[i];
d105 1
a105 1
    if (CrashInfo) {
a108 7
      } else if (llvm::sys::path::filename(Arg) == MainFilename &&
                 (i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) {
        // Replace the input file name with the crashinfo's file name.
        OS << ' ';
        StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename);
        PrintArg(OS, ShortName.str().c_str(), Quote);
        continue;
a113 1
  }
d115 4
a118 15
  if (CrashInfo && !CrashInfo->VFSPath.empty()) {
    OS << ' ';
    PrintArg(OS, "-ivfsoverlay", Quote);
    OS << ' ';
    PrintArg(OS, CrashInfo->VFSPath.str().c_str(), Quote);
  }

  if (ResponseFile != nullptr) {
    OS << "\n Arguments passed via response file:\n";
    writeResponseFile(OS);
    // Avoiding duplicated newline terminator, since FileLists are
    // newline-separated.
    if (Creator.getResponseFilesSupport() != Tool::RF_FileList)
      OS << "\n";
    OS << " (end of response file)";
a119 1

a122 6
void Command::setResponseFile(const char *FileName) {
  ResponseFile = FileName;
  ResponseFileFlag = Creator.getResponseFileFlag();
  ResponseFileFlag += FileName;
}

d126 3
a128 21

  if (ResponseFile == nullptr) {
    Argv.push_back(Executable);
    for (size_t i = 0, e = Arguments.size(); i != e; ++i)
      Argv.push_back(Arguments[i]);
    Argv.push_back(nullptr);

    return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
                                     Redirects, /*secondsToWait*/ 0,
                                     /*memoryLimit*/ 0, ErrMsg,
                                     ExecutionFailed);
  }

  // We need to put arguments in a response file (command is too large)
  // Open stream to store the response file contents
  std::string RespContents;
  llvm::raw_string_ostream SS(RespContents);

  // Write file contents and build the Argv vector
  writeResponseFile(SS);
  buildArgvForResponseFile(Argv);
a129 11
  SS.flush();

  // Save the response file in the appropriate encoding
  if (std::error_code EC = writeFileWithEncoding(
          ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
    if (ErrMsg)
      *ErrMsg = EC.message();
    if (ExecutionFailed)
      *ExecutionFailed = true;
    return -1;
  }
d139 3
a141 3
                                 std::unique_ptr<Command> Fallback_)
    : Command(Source_, Creator_, Executable_, Arguments_),
      Fallback(std::move(Fallback_)) {}
d144 2
a145 2
                            bool Quote, CrashReportInfo *CrashInfo) const {
  Command::Print(OS, "", Quote, CrashInfo);
d147 1
a147 1
  Fallback->Print(OS, Terminator, Quote, CrashInfo);
d178 5
d184 3
a186 3
                    CrashReportInfo *CrashInfo) const {
  for (const auto &Job : *this)
    Job.Print(OS, Terminator, Quote, CrashInfo);
d189 3
a191 1
void JobList::clear() { Jobs.clear(); }
@


1.1.1.6
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a9 1
#include "InputInfo.h"
d28 8
a35 9
Command::Command(const Action &Source, const Tool &Creator,
                 const char *Executable, const ArgStringList &Arguments,
                 ArrayRef<InputInfo> Inputs)
    : Source(Source), Creator(Creator), Executable(Executable),
      Arguments(Arguments), ResponseFile(nullptr) {
  for (const auto &II : Inputs)
    if (II.isFilename())
      InputFilenames.push_back(II.getFilename());
}
d37 1
a37 1
static int skipArgs(const char *Flag, bool HaveCrashVFS) {
d46 1
a46 1
    .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
a48 3
    .Cases("-header-include-file", "-diagnostic-log-file", true)
    // Some include flags shouldn't be skipped if we have a crash VFS
    .Case("-isysroot", !HaveCrashVFS)
d76 1
a76 1
void Command::printArg(raw_ostream &OS, const char *Arg, bool Quote) {
d103 1
a103 3
  // In regular response files, we send all arguments to the response file.
  // Wrapping all arguments in double quotes ensures that both Unix tools and
  // Windows tools understand the response file.
d151 1
a151 1
  printArg(OS, Executable, /*Quote=*/true);
d160 7
a166 1
  bool HaveCrashVFS = CrashInfo && !CrashInfo->VFSPath.empty();
d171 1
a171 1
      if (int Skip = skipArgs(Arg, HaveCrashVFS)) {
d174 2
a175 5
      }
      auto Found = std::find_if(InputFilenames.begin(), InputFilenames.end(),
                                [&Arg](StringRef IF) { return IF == Arg; });
      if (Found != InputFilenames.end() &&
          (i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) {
d179 1
a179 1
        printArg(OS, ShortName.str().c_str(), Quote);
d185 1
a185 1
    printArg(OS, Arg, Quote);
d188 1
a188 1
  if (CrashInfo && HaveCrashVFS) {
d190 1
a190 1
    printArg(OS, "-ivfsoverlay", Quote);
d192 1
a192 1
    printArg(OS, CrashInfo->VFSPath.str().c_str(), Quote);
d220 2
a221 1
    Argv.append(Arguments.begin(), Arguments.end());
a258 1
                                 ArrayRef<InputInfo> Inputs,
d260 1
a260 1
    : Command(Source_, Creator_, Executable_, Arguments_, Inputs),
d296 2
@


1.1.1.6.2.1
log
@Sync with HEAD
@
text
@a9 1
#include "clang/Driver/Job.h"
d13 1
a17 1
#include "llvm/ADT/SmallString.h"
a20 2
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
d39 1
a39 6
/// @@brief Check if the compiler flag in question should be skipped when
/// emitting a reproducer. Also track how many arguments it has and if the
/// option is some kind of include path.
static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
                     bool &IsInclude) {
  SkipNum = 2;
d42 2
a43 2
  bool ShouldSkip = llvm::StringSwitch<bool>(Flag)
    .Cases("-MF", "-MT", "-MQ", "-serialize-diagnostic-file", true)
d45 5
a49 1
    .Cases("-fdebug-compilation-dir", "-diagnostic-log-file", true)
d51 3
a54 2
  if (ShouldSkip)
    return true;
d56 3
a58 11
  // Some include flags shouldn't be skipped if we have a crash VFS
  IsInclude = llvm::StringSwitch<bool>(Flag)
    .Cases("-include", "-header-include-file", true)
    .Cases("-idirafter", "-internal-isystem", "-iwithprefix", true)
    .Cases("-internal-externc-isystem", "-iprefix", true)
    .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
    .Cases("-isysroot", "-I", "-F", "-resource-dir", true)
    .Cases("-iframework", "-include-pch", true)
    .Default(false);
  if (IsInclude)
    return HaveCrashVFS ? false : true;
d63 1
a63 1
  ShouldSkip = llvm::StringSwitch<bool>(Flag)
d69 2
a70 3
  SkipNum = 1;
  if (ShouldSkip)
    return true;
d74 3
a76 5
  IsInclude = FlagRef.startswith("-F") || FlagRef.startswith("-I");
  if (IsInclude)
    return HaveCrashVFS ? false : true;
  if (FlagRef.startswith("-fmodules-cache-path="))
    return true;
d78 1
a78 2
  SkipNum = 0;
  return false;
d81 2
a82 2
void Command::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
  const bool Escape = Arg.find_first_of("\"\\$") != StringRef::npos;
d91 1
a91 1
  for (const char c : Arg) {
a153 39
/// @@brief Rewrite relative include-like flag paths to absolute ones.
static void
rewriteIncludes(const llvm::ArrayRef<const char *> &Args, size_t Idx,
                size_t NumArgs,
                llvm::SmallVectorImpl<llvm::SmallString<128>> &IncFlags) {
  using namespace llvm;
  using namespace sys;
  auto getAbsPath = [](StringRef InInc, SmallVectorImpl<char> &OutInc) -> bool {
    if (path::is_absolute(InInc)) // Nothing to do here...
      return false;
    std::error_code EC = fs::current_path(OutInc);
    if (EC)
      return false;
    path::append(OutInc, InInc);
    return true;
  };

  SmallString<128> NewInc;
  if (NumArgs == 1) {
    StringRef FlagRef(Args[Idx + NumArgs - 1]);
    assert((FlagRef.startswith("-F") || FlagRef.startswith("-I")) &&
            "Expecting -I or -F");
    StringRef Inc = FlagRef.slice(2, StringRef::npos);
    if (getAbsPath(Inc, NewInc)) {
      SmallString<128> NewArg(FlagRef.slice(0, 2));
      NewArg += NewInc;
      IncFlags.push_back(std::move(NewArg));
    }
    return;
  }

  assert(NumArgs == 2 && "Not expecting more than two arguments");
  StringRef Inc(Args[Idx + NumArgs - 1]);
  if (!getAbsPath(Inc, NewInc))
    return;
  IncFlags.push_back(SmallString<128>(Args[Idx]));
  IncFlags.push_back(std::move(NewInc));
}

d172 2
a173 4
      int NumArgs = 0;
      bool IsInclude = false;
      if (skipArgs(Arg, HaveCrashVFS, NumArgs, IsInclude)) {
        i += NumArgs - 1;
a175 15

      // Relative includes need to be expanded to absolute paths.
      if (HaveCrashVFS && IsInclude) {
        SmallVector<SmallString<128>, 2> NewIncFlags;
        rewriteIncludes(Args, i, NumArgs, NewIncFlags);
        if (!NewIncFlags.empty()) {
          for (auto &F : NewIncFlags) {
            OS << ' ';
            printArg(OS, F.c_str(), Quote);
          }
          i += NumArgs - 1;
          continue;
        }
      }

d183 1
a183 1
        printArg(OS, ShortName.str(), Quote);
d196 1
a196 16
    printArg(OS, CrashInfo->VFSPath.str(), Quote);

    // The leftover modules from the crash are stored in
    //  <name>.cache/vfs/modules
    // Leave it untouched for pcm inspection and provide a clean/empty dir
    // path to contain the future generated module cache:
    //  <name>.cache/vfs/repro-modules
    SmallString<128> RelModCacheDir = llvm::sys::path::parent_path(
        llvm::sys::path::parent_path(CrashInfo->VFSPath));
    llvm::sys::path::append(RelModCacheDir, "repro-modules");

    std::string ModCachePath = "-fmodules-cache-path=";
    ModCachePath.append(RelModCacheDir.c_str());

    OS << ' ';
    printArg(OS, ModCachePath, Quote);
a299 23
ForceSuccessCommand::ForceSuccessCommand(const Action &Source_,
                                         const Tool &Creator_,
                                         const char *Executable_,
                                         const ArgStringList &Arguments_,
                                         ArrayRef<InputInfo> Inputs)
    : Command(Source_, Creator_, Executable_, Arguments_, Inputs) {}

void ForceSuccessCommand::Print(raw_ostream &OS, const char *Terminator,
                            bool Quote, CrashReportInfo *CrashInfo) const {
  Command::Print(OS, "", Quote, CrashInfo);
  OS << " || (exit 0)" << Terminator;
}

int ForceSuccessCommand::Execute(const StringRef **Redirects,
                                 std::string *ErrMsg,
                                 bool *ExecutionFailed) const {
  int Status = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
  (void)Status;
  if (ExecutionFailed)
    *ExecutionFailed = false;
  return 0;
}

@


1.1.1.7
log
@Import Clang pre-4.0.0 r291444.
@
text
@a9 1
#include "clang/Driver/Job.h"
d13 1
a17 1
#include "llvm/ADT/SmallString.h"
a20 2
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
d39 1
a39 6
/// @@brief Check if the compiler flag in question should be skipped when
/// emitting a reproducer. Also track how many arguments it has and if the
/// option is some kind of include path.
static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
                     bool &IsInclude) {
  SkipNum = 2;
d42 2
a43 2
  bool ShouldSkip = llvm::StringSwitch<bool>(Flag)
    .Cases("-MF", "-MT", "-MQ", "-serialize-diagnostic-file", true)
d45 5
a49 1
    .Cases("-fdebug-compilation-dir", "-diagnostic-log-file", true)
d51 3
a54 2
  if (ShouldSkip)
    return true;
d56 3
a58 11
  // Some include flags shouldn't be skipped if we have a crash VFS
  IsInclude = llvm::StringSwitch<bool>(Flag)
    .Cases("-include", "-header-include-file", true)
    .Cases("-idirafter", "-internal-isystem", "-iwithprefix", true)
    .Cases("-internal-externc-isystem", "-iprefix", true)
    .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
    .Cases("-isysroot", "-I", "-F", "-resource-dir", true)
    .Cases("-iframework", "-include-pch", true)
    .Default(false);
  if (IsInclude)
    return HaveCrashVFS ? false : true;
d63 1
a63 1
  ShouldSkip = llvm::StringSwitch<bool>(Flag)
d69 2
a70 3
  SkipNum = 1;
  if (ShouldSkip)
    return true;
d74 3
a76 5
  IsInclude = FlagRef.startswith("-F") || FlagRef.startswith("-I");
  if (IsInclude)
    return HaveCrashVFS ? false : true;
  if (FlagRef.startswith("-fmodules-cache-path="))
    return true;
d78 1
a78 2
  SkipNum = 0;
  return false;
d81 2
a82 2
void Command::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
  const bool Escape = Arg.find_first_of("\"\\$") != StringRef::npos;
d91 1
a91 1
  for (const char c : Arg) {
a153 39
/// @@brief Rewrite relative include-like flag paths to absolute ones.
static void
rewriteIncludes(const llvm::ArrayRef<const char *> &Args, size_t Idx,
                size_t NumArgs,
                llvm::SmallVectorImpl<llvm::SmallString<128>> &IncFlags) {
  using namespace llvm;
  using namespace sys;
  auto getAbsPath = [](StringRef InInc, SmallVectorImpl<char> &OutInc) -> bool {
    if (path::is_absolute(InInc)) // Nothing to do here...
      return false;
    std::error_code EC = fs::current_path(OutInc);
    if (EC)
      return false;
    path::append(OutInc, InInc);
    return true;
  };

  SmallString<128> NewInc;
  if (NumArgs == 1) {
    StringRef FlagRef(Args[Idx + NumArgs - 1]);
    assert((FlagRef.startswith("-F") || FlagRef.startswith("-I")) &&
            "Expecting -I or -F");
    StringRef Inc = FlagRef.slice(2, StringRef::npos);
    if (getAbsPath(Inc, NewInc)) {
      SmallString<128> NewArg(FlagRef.slice(0, 2));
      NewArg += NewInc;
      IncFlags.push_back(std::move(NewArg));
    }
    return;
  }

  assert(NumArgs == 2 && "Not expecting more than two arguments");
  StringRef Inc(Args[Idx + NumArgs - 1]);
  if (!getAbsPath(Inc, NewInc))
    return;
  IncFlags.push_back(SmallString<128>(Args[Idx]));
  IncFlags.push_back(std::move(NewInc));
}

d172 2
a173 4
      int NumArgs = 0;
      bool IsInclude = false;
      if (skipArgs(Arg, HaveCrashVFS, NumArgs, IsInclude)) {
        i += NumArgs - 1;
a175 15

      // Relative includes need to be expanded to absolute paths.
      if (HaveCrashVFS && IsInclude) {
        SmallVector<SmallString<128>, 2> NewIncFlags;
        rewriteIncludes(Args, i, NumArgs, NewIncFlags);
        if (!NewIncFlags.empty()) {
          for (auto &F : NewIncFlags) {
            OS << ' ';
            printArg(OS, F.c_str(), Quote);
          }
          i += NumArgs - 1;
          continue;
        }
      }

d183 1
a183 1
        printArg(OS, ShortName.str(), Quote);
d196 1
a196 16
    printArg(OS, CrashInfo->VFSPath.str(), Quote);

    // The leftover modules from the crash are stored in
    //  <name>.cache/vfs/modules
    // Leave it untouched for pcm inspection and provide a clean/empty dir
    // path to contain the future generated module cache:
    //  <name>.cache/vfs/repro-modules
    SmallString<128> RelModCacheDir = llvm::sys::path::parent_path(
        llvm::sys::path::parent_path(CrashInfo->VFSPath));
    llvm::sys::path::append(RelModCacheDir, "repro-modules");

    std::string ModCachePath = "-fmodules-cache-path=";
    ModCachePath.append(RelModCacheDir.c_str());

    OS << ' ';
    printArg(OS, ModCachePath, Quote);
a299 23
ForceSuccessCommand::ForceSuccessCommand(const Action &Source_,
                                         const Tool &Creator_,
                                         const char *Executable_,
                                         const ArgStringList &Arguments_,
                                         ArrayRef<InputInfo> Inputs)
    : Command(Source_, Creator_, Executable_, Arguments_, Inputs) {}

void ForceSuccessCommand::Print(raw_ostream &OS, const char *Terminator,
                            bool Quote, CrashReportInfo *CrashInfo) const {
  Command::Print(OS, "", Quote, CrashInfo);
  OS << " || (exit 0)" << Terminator;
}

int ForceSuccessCommand::Execute(const StringRef **Redirects,
                                 std::string *ErrMsg,
                                 bool *ExecutionFailed) const {
  int Status = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
  (void)Status;
  if (ExecutionFailed)
    *ExecutionFailed = false;
  return 0;
}

@


1.1.1.8
log
@Import clang r309604 from branches/release_50
@
text
@d52 1
a52 1
    .Cases("-o", "-dependency-file", true)
a303 6
void Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
  Environment.reserve(NewEnvironment.size() + 1);
  Environment.assign(NewEnvironment.begin(), NewEnvironment.end());
  Environment.push_back(nullptr);
}

a307 9
  const char **Envp;
  if (Environment.empty()) {
    Envp = nullptr;
  } else {
    assert(Environment.back() == nullptr &&
           "Environment vector should be null-terminated by now");
    Envp = const_cast<const char **>(Environment.data());
  }

d313 4
a316 3
    return llvm::sys::ExecuteAndWait(
        Executable, Argv.data(), Envp, Redirects, /*secondsToWait*/ 0,
        /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
d340 2
a341 2
  return llvm::sys::ExecuteAndWait(Executable, Argv.data(), Envp, Redirects,
                                   /*secondsToWait*/ 0,
@


1.1.1.8.4.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
//===- Job.cpp - Command to Execute ---------------------------------------===//
a11 1
#include "clang/Basic/LLVM.h"
d17 1
a18 1
#include "llvm/ADT/SmallVector.h"
a25 1
#include <algorithm>
d27 4
a30 7
#include <cstddef>
#include <string>
#include <system_error>
#include <utility>

using namespace clang;
using namespace driver;
d36 1
a36 1
      Arguments(Arguments) {
d42 1
a42 1
/// Check if the compiler flag in question should be skipped when
d69 1
a69 1
    return !HaveCrashVFS;
d88 1
a88 1
    return !HaveCrashVFS;
d106 1
a106 1
  for (const auto c : Arg) {
d117 1
a117 1
    for (const auto *Arg : InputFileList) {
d126 1
a126 1
  for (const auto *Arg : Arguments) {
d152 1
a152 1
  for (const auto *InputName : InputFileList)
d158 1
a158 1
  for (const auto *Arg : Arguments) {
d169 1
a169 1
/// Rewrite relative include-like flag paths to absolute ones.
a175 1

d214 2
a215 2
  ArrayRef<const char *> Args = Arguments;
  SmallVector<const char *, 128> ArgsRespFile;
d310 2
a311 2
int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
                     std::string *ErrMsg, bool *ExecutionFailed) const {
d314 4
a317 3
  Optional<ArrayRef<StringRef>> Env;
  std::vector<StringRef> ArgvVectorStorage;
  if (!Environment.empty()) {
d320 1
a320 2
    ArgvVectorStorage = llvm::toStringRefArray(Environment.data());
    Env = makeArrayRef(ArgvVectorStorage);
a327 1
    auto Args = llvm::toStringRefArray(Argv.data());
d329 1
a329 1
        Executable, Args, Env, Redirects, /*secondsToWait*/ 0,
d354 1
a354 2
  auto Args = llvm::toStringRefArray(Argv.data());
  return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
d381 2
a382 2
int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
                             std::string *ErrMsg, bool *ExecutionFailed) const {
d413 1
a413 1
int ForceSuccessCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
@


1.1.1.8.4.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.8.2.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
//===- Job.cpp - Command to Execute ---------------------------------------===//
a11 1
#include "clang/Basic/LLVM.h"
d17 1
a18 1
#include "llvm/ADT/SmallVector.h"
a25 1
#include <algorithm>
d27 4
a30 7
#include <cstddef>
#include <string>
#include <system_error>
#include <utility>

using namespace clang;
using namespace driver;
d36 1
a36 1
      Arguments(Arguments) {
d42 1
a42 1
/// Check if the compiler flag in question should be skipped when
d69 1
a69 1
    return !HaveCrashVFS;
d88 1
a88 1
    return !HaveCrashVFS;
d106 1
a106 1
  for (const auto c : Arg) {
d117 1
a117 1
    for (const auto *Arg : InputFileList) {
d126 1
a126 1
  for (const auto *Arg : Arguments) {
d152 1
a152 1
  for (const auto *InputName : InputFileList)
d158 1
a158 1
  for (const auto *Arg : Arguments) {
d169 1
a169 1
/// Rewrite relative include-like flag paths to absolute ones.
a175 1

d214 2
a215 2
  ArrayRef<const char *> Args = Arguments;
  SmallVector<const char *, 128> ArgsRespFile;
d310 2
a311 2
int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
                     std::string *ErrMsg, bool *ExecutionFailed) const {
d314 4
a317 3
  Optional<ArrayRef<StringRef>> Env;
  std::vector<StringRef> ArgvVectorStorage;
  if (!Environment.empty()) {
d320 1
a320 2
    ArgvVectorStorage = llvm::toStringRefArray(Environment.data());
    Env = makeArrayRef(ArgvVectorStorage);
a327 1
    auto Args = llvm::toStringRefArray(Argv.data());
d329 1
a329 1
        Executable, Args, Env, Redirects, /*secondsToWait*/ 0,
d354 1
a354 2
  auto Args = llvm::toStringRefArray(Argv.data());
  return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
d381 2
a382 2
int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
                             std::string *ErrMsg, bool *ExecutionFailed) const {
d413 1
a413 1
int ForceSuccessCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
@


1.1.1.9
log
@Import clang r337282 from trunk
@
text
@d1 1
a1 1
//===- Job.cpp - Command to Execute ---------------------------------------===//
a11 1
#include "clang/Basic/LLVM.h"
d17 1
a18 1
#include "llvm/ADT/SmallVector.h"
a25 1
#include <algorithm>
d27 4
a30 7
#include <cstddef>
#include <string>
#include <system_error>
#include <utility>

using namespace clang;
using namespace driver;
d36 1
a36 1
      Arguments(Arguments) {
d42 1
a42 1
/// Check if the compiler flag in question should be skipped when
d69 1
a69 1
    return !HaveCrashVFS;
d88 1
a88 1
    return !HaveCrashVFS;
d106 1
a106 1
  for (const auto c : Arg) {
d117 1
a117 1
    for (const auto *Arg : InputFileList) {
d126 1
a126 1
  for (const auto *Arg : Arguments) {
d152 1
a152 1
  for (const auto *InputName : InputFileList)
d158 1
a158 1
  for (const auto *Arg : Arguments) {
d169 1
a169 1
/// Rewrite relative include-like flag paths to absolute ones.
a175 1

d214 2
a215 2
  ArrayRef<const char *> Args = Arguments;
  SmallVector<const char *, 128> ArgsRespFile;
d310 2
a311 2
int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
                     std::string *ErrMsg, bool *ExecutionFailed) const {
d314 4
a317 3
  Optional<ArrayRef<StringRef>> Env;
  std::vector<StringRef> ArgvVectorStorage;
  if (!Environment.empty()) {
d320 1
a320 2
    ArgvVectorStorage = llvm::toStringRefArray(Environment.data());
    Env = makeArrayRef(ArgvVectorStorage);
a327 1
    auto Args = llvm::toStringRefArray(Argv.data());
d329 1
a329 1
        Executable, Args, Env, Redirects, /*secondsToWait*/ 0,
d354 1
a354 2
  auto Args = llvm::toStringRefArray(Argv.data());
  return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
d381 2
a382 2
int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
                             std::string *ErrMsg, bool *ExecutionFailed) const {
d413 1
a413 1
int ForceSuccessCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
@


1.1.1.10
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.4.4.1
log
@file Job.cpp was added on branch tls-maxphys on 2014-08-19 23:47:27 +0000
@
text
@d1 191
@


1.1.1.4.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 191
//===--- Job.cpp - Command to Execute -------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
using namespace clang::driver;
using llvm::raw_ostream;
using llvm::StringRef;

Job::~Job() {}

Command::Command(const Action &_Source, const Tool &_Creator,
                 const char *_Executable,
                 const ArgStringList &_Arguments)
    : Job(CommandClass), Source(_Source), Creator(_Creator),
      Executable(_Executable), Arguments(_Arguments) {}

static int skipArgs(const char *Flag) {
  // These flags are all of the form -Flag <Arg> and are treated as two
  // arguments.  Therefore, we need to skip the flag and the next argument.
  bool Res = llvm::StringSwitch<bool>(Flag)
    .Cases("-I", "-MF", "-MT", "-MQ", true)
    .Cases("-o", "-coverage-file", "-dependency-file", true)
    .Cases("-fdebug-compilation-dir", "-idirafter", true)
    .Cases("-include", "-include-pch", "-internal-isystem", true)
    .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
    .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true)
    .Cases("-resource-dir", "-serialize-diagnostic-file", true)
    .Cases("-dwarf-debug-flags", "-ivfsoverlay", true)
    .Default(false);

  // Match found.
  if (Res)
    return 2;

  // The remaining flags are treated as a single argument.

  // These flags are all of the form -Flag and have no second argument.
  Res = llvm::StringSwitch<bool>(Flag)
    .Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
    .Case("-MMD", true)
    .Default(false);

  // Match found.
  if (Res)
    return 1;

  // These flags are treated as a single argument (e.g., -F<Dir>).
  StringRef FlagRef(Flag);
  if (FlagRef.startswith("-F") || FlagRef.startswith("-I") ||
      FlagRef.startswith("-fmodules-cache-path="))
    return 1;

  return 0;
}

static bool quoteNextArg(const char *flag) {
  return llvm::StringSwitch<bool>(flag)
    .Case("-D", true)
    .Default(false);
}

static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) {
  const bool Escape = std::strpbrk(Arg, "\"\\$");

  if (!Quote && !Escape) {
    OS << Arg;
    return;
  }

  // Quote and escape. This isn't really complete, but good enough.
  OS << '"';
  while (const char c = *Arg++) {
    if (c == '"' || c == '\\' || c == '$')
      OS << '\\';
    OS << c;
  }
  OS << '"';
}

void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
                    bool CrashReport) const {
  // Always quote the exe.
  OS << ' ';
  PrintArg(OS, Executable, /*Quote=*/true);

  for (size_t i = 0, e = Arguments.size(); i < e; ++i) {
    const char *const Arg = Arguments[i];

    if (CrashReport) {
      if (int Skip = skipArgs(Arg)) {
        i += Skip - 1;
        continue;
      }
    }

    OS << ' ';
    PrintArg(OS, Arg, Quote);

    if (CrashReport && quoteNextArg(Arg) && i + 1 < e) {
      OS << ' ';
      PrintArg(OS, Arguments[++i], true);
    }
  }
  OS << Terminator;
}

int Command::Execute(const StringRef **Redirects, std::string *ErrMsg,
                     bool *ExecutionFailed) const {
  SmallVector<const char*, 128> Argv;
  Argv.push_back(Executable);
  for (size_t i = 0, e = Arguments.size(); i != e; ++i)
    Argv.push_back(Arguments[i]);
  Argv.push_back(nullptr);

  return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
                                   Redirects, /*secondsToWait*/ 0,
                                   /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}

FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
                                 const char *Executable_,
                                 const ArgStringList &Arguments_,
                                 Command *Fallback_)
    : Command(Source_, Creator_, Executable_, Arguments_), Fallback(Fallback_) {
}

void FallbackCommand::Print(raw_ostream &OS, const char *Terminator,
                            bool Quote, bool CrashReport) const {
  Command::Print(OS, "", Quote, CrashReport);
  OS << " ||";
  Fallback->Print(OS, Terminator, Quote, CrashReport);
}

static bool ShouldFallback(int ExitCode) {
  // FIXME: We really just want to fall back for internal errors, such
  // as when some symbol cannot be mangled, when we should be able to
  // parse something but can't, etc.
  return ExitCode != 0;
}

int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg,
                             bool *ExecutionFailed) const {
  int PrimaryStatus = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
  if (!ShouldFallback(PrimaryStatus))
    return PrimaryStatus;

  // Clear ExecutionFailed and ErrMsg before falling back.
  if (ErrMsg)
    ErrMsg->clear();
  if (ExecutionFailed)
    *ExecutionFailed = false;

  const Driver &D = getCreator().getToolChain().getDriver();
  D.Diag(diag::warn_drv_invoking_fallback) << Fallback->getExecutable();

  int SecondaryStatus = Fallback->Execute(Redirects, ErrMsg, ExecutionFailed);
  return SecondaryStatus;
}

JobList::JobList() : Job(JobListClass) {}

JobList::~JobList() {
  for (iterator it = begin(), ie = end(); it != ie; ++it)
    delete *it;
}

void JobList::Print(raw_ostream &OS, const char *Terminator, bool Quote,
                    bool CrashReport) const {
  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
    (*it)->Print(OS, Terminator, Quote, CrashReport);
}

void JobList::clear() {
  DeleteContainerPointers(Jobs);
}
@


1.1.1.2.4.1
log
@file Job.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:27 +0000
@
text
@d1 188
@


1.1.1.2.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 188
//===--- Job.cpp - Command to Execute -------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
using namespace clang::driver;
using llvm::raw_ostream;
using llvm::StringRef;

Job::~Job() {}

Command::Command(const Action &_Source, const Tool &_Creator,
                 const char *_Executable,
                 const ArgStringList &_Arguments)
    : Job(CommandClass), Source(_Source), Creator(_Creator),
      Executable(_Executable), Arguments(_Arguments) {}

static int skipArgs(const char *Flag) {
  // These flags are all of the form -Flag <Arg> and are treated as two
  // arguments.  Therefore, we need to skip the flag and the next argument.
  bool Res = llvm::StringSwitch<bool>(Flag)
    .Cases("-I", "-MF", "-MT", "-MQ", true)
    .Cases("-o", "-coverage-file", "-dependency-file", true)
    .Cases("-fdebug-compilation-dir", "-idirafter", true)
    .Cases("-include", "-include-pch", "-internal-isystem", true)
    .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
    .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true)
    .Cases("-resource-dir", "-serialize-diagnostic-file", true)
    .Case("-dwarf-debug-flags", true)
    .Default(false);

  // Match found.
  if (Res)
    return 2;

  // The remaining flags are treated as a single argument.

  // These flags are all of the form -Flag and have no second argument.
  Res = llvm::StringSwitch<bool>(Flag)
    .Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
    .Case("-MMD", true)
    .Default(false);

  // Match found.
  if (Res)
    return 1;

  // These flags are treated as a single argument (e.g., -F<Dir>).
  StringRef FlagRef(Flag);
  if (FlagRef.startswith("-F") || FlagRef.startswith("-I"))
    return 1;

  return 0;
}

static bool quoteNextArg(const char *flag) {
  return llvm::StringSwitch<bool>(flag)
    .Case("-D", true)
    .Default(false);
}

static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) {
  const bool Escape = std::strpbrk(Arg, "\"\\$");

  if (!Quote && !Escape) {
    OS << Arg;
    return;
  }

  // Quote and escape. This isn't really complete, but good enough.
  OS << '"';
  while (const char c = *Arg++) {
    if (c == '"' || c == '\\' || c == '$')
      OS << '\\';
    OS << c;
  }
  OS << '"';
}

void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
                    bool CrashReport) const {
  OS << " \"" << Executable << '"';

  for (size_t i = 0, e = Arguments.size(); i < e; ++i) {
    const char *const Arg = Arguments[i];

    if (CrashReport) {
      if (int Skip = skipArgs(Arg)) {
        i += Skip - 1;
        continue;
      }
    }

    OS << ' ';
    PrintArg(OS, Arg, Quote);

    if (CrashReport && quoteNextArg(Arg) && i + 1 < e) {
      OS << ' ';
      PrintArg(OS, Arguments[++i], true);
    }
  }
  OS << Terminator;
}

int Command::Execute(const StringRef **Redirects, std::string *ErrMsg,
                     bool *ExecutionFailed) const {
  SmallVector<const char*, 128> Argv;
  Argv.push_back(Executable);
  for (size_t i = 0, e = Arguments.size(); i != e; ++i)
    Argv.push_back(Arguments[i]);
  Argv.push_back(0);

  return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ 0,
                                   Redirects, /*secondsToWait*/ 0,
                                   /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}

FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
                                 const char *Executable_,
                                 const ArgStringList &Arguments_,
                                 Command *Fallback_)
    : Command(Source_, Creator_, Executable_, Arguments_), Fallback(Fallback_) {
}

void FallbackCommand::Print(raw_ostream &OS, const char *Terminator,
                            bool Quote, bool CrashReport) const {
  Command::Print(OS, "", Quote, CrashReport);
  OS << " ||";
  Fallback->Print(OS, Terminator, Quote, CrashReport);
}

static bool ShouldFallback(int ExitCode) {
  // FIXME: We really just want to fall back for internal errors, such
  // as when some symbol cannot be mangled, when we should be able to
  // parse something but can't, etc.
  return ExitCode != 0;
}

int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg,
                             bool *ExecutionFailed) const {
  int PrimaryStatus = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
  if (!ShouldFallback(PrimaryStatus))
    return PrimaryStatus;

  // Clear ExecutionFailed and ErrMsg before falling back.
  if (ErrMsg)
    ErrMsg->clear();
  if (ExecutionFailed)
    *ExecutionFailed = false;

  const Driver &D = getCreator().getToolChain().getDriver();
  D.Diag(diag::warn_drv_invoking_fallback) << Fallback->getExecutable();

  int SecondaryStatus = Fallback->Execute(Redirects, ErrMsg, ExecutionFailed);
  return SecondaryStatus;
}

JobList::JobList() : Job(JobListClass) {}

JobList::~JobList() {
  for (iterator it = begin(), ie = end(); it != ie; ++it)
    delete *it;
}

void JobList::Print(raw_ostream &OS, const char *Terminator, bool Quote,
                    bool CrashReport) const {
  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
    (*it)->Print(OS, Terminator, Quote, CrashReport);
}

void JobList::clear() {
  DeleteContainerPointers(Jobs);
}
@


