Check in LLVM r95781.
diff --git a/lib/Driver/Arg.cpp b/lib/Driver/Arg.cpp
new file mode 100644
index 0000000..a09ba09
--- /dev/null
+++ b/lib/Driver/Arg.cpp
@@ -0,0 +1,191 @@
+//===--- Arg.cpp - Argument Implementations -----------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Option.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+
+Arg::Arg(ArgClass _Kind, const Option *_Opt, unsigned _Index,
+         const Arg *_BaseArg)
+  : Kind(_Kind), Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false) {
+}
+
+Arg::~Arg() { }
+
+void Arg::dump() const {
+  llvm::errs() << "<";
+  switch (Kind) {
+  default:
+    assert(0 && "Invalid kind");
+#define P(N) case N: llvm::errs() << #N; break
+    P(FlagClass);
+    P(PositionalClass);
+    P(JoinedClass);
+    P(SeparateClass);
+    P(CommaJoinedClass);
+    P(JoinedAndSeparateClass);
+#undef P
+  }
+
+  llvm::errs() << " Opt:";
+  Opt->dump();
+
+  llvm::errs() << " Index:" << Index;
+
+  if (isa<CommaJoinedArg>(this) || isa<SeparateArg>(this))
+    llvm::errs() << " NumValues:" << getNumValues();
+
+  llvm::errs() << ">\n";
+}
+
+std::string Arg::getAsString(const ArgList &Args) const {
+  std::string Res;
+  llvm::raw_string_ostream OS(Res);
+
+  ArgStringList ASL;
+  render(Args, ASL);
+  for (ArgStringList::iterator
+         it = ASL.begin(), ie = ASL.end(); it != ie; ++it) {
+    if (it != ASL.begin())
+      OS << ' ';
+    OS << *it;
+  }
+
+  return OS.str();
+}
+
+void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const {
+  if (!getOption().hasNoOptAsInput()) {
+    render(Args, Output);
+    return;
+  }
+
+  for (unsigned i = 0, e = getNumValues(); i != e; ++i)
+    Output.push_back(getValue(Args, i));
+}
+
+FlagArg::FlagArg(const Option *Opt, unsigned Index, const Arg *BaseArg)
+  : Arg(FlagClass, Opt, Index, BaseArg) {
+}
+
+void FlagArg::render(const ArgList &Args, ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+}
+
+const char *FlagArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(0 && "Invalid index.");
+  return 0;
+}
+
+PositionalArg::PositionalArg(const Option *Opt, unsigned Index,
+                             const Arg *BaseArg)
+  : Arg(PositionalClass, Opt, Index, BaseArg) {
+}
+
+void PositionalArg::render(const ArgList &Args, ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+}
+
+const char *PositionalArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  return Args.getArgString(getIndex());
+}
+
+JoinedArg::JoinedArg(const Option *Opt, unsigned Index, const Arg *BaseArg)
+  : Arg(JoinedClass, Opt, Index, BaseArg) {
+}
+
+void JoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
+  if (getOption().hasForceSeparateRender()) {
+    Output.push_back(getOption().getName());
+    Output.push_back(getValue(Args, 0));
+  } else {
+    Output.push_back(Args.getArgString(getIndex()));
+  }
+}
+
+const char *JoinedArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  // FIXME: Avoid strlen.
+  return Args.getArgString(getIndex()) + strlen(getOption().getName());
+}
+
+CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index,
+                               const char *Str, const Arg *BaseArg)
+  : Arg(CommaJoinedClass, Opt, Index, BaseArg) {
+  const char *Prev = Str;
+  for (;; ++Str) {
+    char c = *Str;
+
+    if (!c) {
+      if (Prev != Str)
+        Values.push_back(std::string(Prev, Str));
+      break;
+    } else if (c == ',') {
+      if (Prev != Str)
+        Values.push_back(std::string(Prev, Str));
+      Prev = Str + 1;
+    }
+  }
+}
+
+void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+}
+
+const char *CommaJoinedArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  return Values[N].c_str();
+}
+
+SeparateArg::SeparateArg(const Option *Opt, unsigned Index, unsigned _NumValues,
+                         const Arg *BaseArg)
+  : Arg(SeparateClass, Opt, Index, BaseArg), NumValues(_NumValues) {
+}
+
+void SeparateArg::render(const ArgList &Args, ArgStringList &Output) const {
+  if (getOption().hasForceJoinedRender()) {
+    assert(getNumValues() == 1 && "Cannot force joined render with > 1 args.");
+    // FIXME: Avoid std::string.
+    std::string Joined(getOption().getName());
+    Joined += Args.getArgString(getIndex());
+    Output.push_back(Args.MakeArgString(Joined.c_str()));
+  } else {
+    Output.push_back(Args.getArgString(getIndex()));
+    for (unsigned i = 0; i < NumValues; ++i)
+      Output.push_back(Args.getArgString(getIndex() + 1 + i));
+  }
+}
+
+const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  return Args.getArgString(getIndex() + 1 + N);
+}
+
+JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index,
+                                           const Arg *BaseArg)
+  : Arg(JoinedAndSeparateClass, Opt, Index, BaseArg) {
+}
+
+void JoinedAndSeparateArg::render(const ArgList &Args,
+                                  ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+  Output.push_back(Args.getArgString(getIndex() + 1));
+}
+
+const char *JoinedAndSeparateArg::getValue(const ArgList &Args,
+                                           unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  if (N == 0)
+    return Args.getArgString(getIndex()) + strlen(getOption().getName());
+  return Args.getArgString(getIndex() + 1);
+}