From ba1075689d0d23f39489abca927ef7d88382cbdf Mon Sep 17 00:00:00 2001
From: Michael Spencer <bigcheesegs@gmail.com>
Date: Fri, 17 Aug 2012 14:01:44 -0700
Subject: [PATCH] Make Option non virtual.

---
 include/clang/Driver/Option.h |  165 +-------------
 lib/Driver/Driver.cpp         |    4 +-
 lib/Driver/OptTable.cpp       |   28 +--
 lib/Driver/Option.cpp         |  484 +++++++++++++++++------------------------
 4 files changed, 217 insertions(+), 464 deletions(-)
 rewrite lib/Driver/Option.cpp (69%)

diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h
index e6c4e12..9d86ba6 100644
--- a/include/clang/Driver/Option.h
+++ b/include/clang/Driver/Option.h
@@ -18,7 +18,6 @@ namespace clang {
 namespace driver {
   class Arg;
   class ArgList;
-  class OptionGroup;
 
   /// Option - Abstract representation for a single form of driver
   /// argument.
@@ -63,11 +62,13 @@ namespace driver {
     StringRef Name;
 
     /// Group this option is a member of, if any.
-    const OptionGroup *Group;
+    const Option *Group;
 
     /// Option that this is an alias for, if any.
     const Option *Alias;
 
+    unsigned NumArgs;
+
     /// Unsupported options will be rejected.
     bool Unsupported : 1;
 
@@ -94,16 +95,15 @@ namespace driver {
     /// CC1Option - This option should be accepted by clang -cc1.
     bool CC1Option : 1;
 
-  protected:
-    Option(OptionClass Kind, OptSpecifier ID, const char *Name,
-           const OptionGroup *Group, const Option *Alias);
   public:
-    virtual ~Option();
+    Option(OptionClass Kind, OptSpecifier ID, const char *Name,
+           const Option *Group, const Option *Alias, unsigned Args);
+    ~Option();
 
     unsigned getID() const { return ID.getID(); }
     OptionClass getKind() const { return Kind; }
     StringRef getName() const { return Name; }
-    const OptionGroup *getGroup() const { return Group; }
+    const Option *getGroup() const { return Group; }
     const Option *getAlias() const { return Alias; }
 
     bool isUnsupported() const { return Unsupported; }
@@ -164,158 +164,9 @@ namespace driver {
     /// If the option accepts the current argument, accept() sets
     /// Index to the position where argument parsing should resume
     /// (even if the argument is missing values).
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const = 0;
+    Arg *accept(const ArgList &Args, unsigned &Index) const;
 
     void dump() const;
-
-    static bool classof(const Option *) { return true; }
-  };
-
-  /// OptionGroup - A set of options which are can be handled uniformly
-  /// by the driver.
-  class OptionGroup : public Option {
-  public:
-    OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::GroupClass;
-    }
-    static bool classof(const OptionGroup *) { return true; }
-  };
-
-  // Dummy option classes.
-
-  /// InputOption - Dummy option class for representing driver inputs.
-  class InputOption : public Option {
-  public:
-    InputOption(OptSpecifier ID);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::InputClass;
-    }
-    static bool classof(const InputOption *) { return true; }
-  };
-
-  /// UnknownOption - Dummy option class for represent unknown arguments.
-  class UnknownOption : public Option {
-  public:
-    UnknownOption(OptSpecifier ID);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::UnknownClass;
-    }
-    static bool classof(const UnknownOption *) { return true; }
-  };
-
-  // Normal options.
-
-  class FlagOption : public Option {
-  public:
-    FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
-               const Option *Alias);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::FlagClass;
-    }
-    static bool classof(const FlagOption *) { return true; }
-  };
-
-  class JoinedOption : public Option {
-  public:
-    JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
-                 const Option *Alias);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::JoinedClass;
-    }
-    static bool classof(const JoinedOption *) { return true; }
-  };
-
-  class SeparateOption : public Option {
-  public:
-    SeparateOption(OptSpecifier ID, const char *Name,
-                   const OptionGroup *Group, const Option *Alias);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::SeparateClass;
-    }
-    static bool classof(const SeparateOption *) { return true; }
-  };
-
-  class CommaJoinedOption : public Option {
-  public:
-    CommaJoinedOption(OptSpecifier ID, const char *Name,
-                      const OptionGroup *Group, const Option *Alias);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::CommaJoinedClass;
-    }
-    static bool classof(const CommaJoinedOption *) { return true; }
-  };
-
-  // FIXME: Fold MultiArgOption into SeparateOption?
-
-  /// MultiArgOption - An option which takes multiple arguments (these
-  /// are always separate arguments).
-  class MultiArgOption : public Option {
-    unsigned NumArgs;
-
-  public:
-    MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
-                   const Option *Alias, unsigned NumArgs);
-
-    unsigned getNumArgs() const { return NumArgs; }
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::MultiArgClass;
-    }
-    static bool classof(const MultiArgOption *) { return true; }
-  };
-
-  /// JoinedOrSeparateOption - An option which either literally
-  /// prefixes its (non-empty) value, or is follwed by a value.
-  class JoinedOrSeparateOption : public Option {
-  public:
-    JoinedOrSeparateOption(OptSpecifier ID, const char *Name,
-                           const OptionGroup *Group, const Option *Alias);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::JoinedOrSeparateClass;
-    }
-    static bool classof(const JoinedOrSeparateOption *) { return true; }
-  };
-
-  /// JoinedAndSeparateOption - An option which literally prefixes its
-  /// value and is followed by another value.
-  class JoinedAndSeparateOption : public Option {
-  public:
-    JoinedAndSeparateOption(OptSpecifier ID, const char *Name,
-                            const OptionGroup *Group, const Option *Alias);
-
-    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
-
-    static bool classof(const Option *O) {
-      return O->getKind() == Option::JoinedAndSeparateClass;
-    }
-    static bool classof(const JoinedAndSeparateOption *) { return true; }
   };
 
 } // end namespace driver
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 87d533d..240d66f 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -981,7 +981,7 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
        it != ie; ++it) {
     Arg *A = *it;
 
-    if (isa<InputOption>(A->getOption())) {
+    if (A->getOption().getKind() == Option::InputClass) {
       const char *Value = A->getValue(Args);
       types::ID Ty = types::TY_INVALID;
 
@@ -1337,7 +1337,7 @@ void Driver::BuildJobs(Compilation &C) const {
       // Suppress the warning automatically if this is just a flag, and it is an
       // instance of an argument we already claimed.
       const Option &Opt = A->getOption();
-      if (isa<FlagOption>(Opt)) {
+      if (Opt.getKind() == Option::FlagClass) {
         bool DuplicateClaimed = false;
 
         for (arg_iterator it = C.getArgs().filtered_begin(&Opt),
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index a3e38b2..f8fe059 100644
--- a/lib/Driver/OptTable.cpp
+++ b/lib/Driver/OptTable.cpp
@@ -131,33 +131,11 @@ OptTable::~OptTable() {
 
 Option *OptTable::CreateOption(unsigned id) const {
   const Info &info = getInfo(id);
-  const OptionGroup *Group =
-    cast_or_null<OptionGroup>(getOption(info.GroupID));
+  const Option *Group = getOption(info.GroupID);
   const Option *Alias = getOption(info.AliasID);
 
-  Option *Opt = 0;
-  switch (info.Kind) {
-  case Option::InputClass:
-    Opt = new InputOption(id); break;
-  case Option::UnknownClass:
-    Opt = new UnknownOption(id); break;
-  case Option::GroupClass:
-    Opt = new OptionGroup(id, info.Name, Group); break;
-  case Option::FlagClass:
-    Opt = new FlagOption(id, info.Name, Group, Alias); break;
-  case Option::JoinedClass:
-    Opt = new JoinedOption(id, info.Name, Group, Alias); break;
-  case Option::SeparateClass:
-    Opt = new SeparateOption(id, info.Name, Group, Alias); break;
-  case Option::CommaJoinedClass:
-    Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
-  case Option::MultiArgClass:
-    Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
-  case Option::JoinedOrSeparateClass:
-    Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
-  case Option::JoinedAndSeparateClass:
-    Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
-  }
+  Option *Opt = new Option(Option::OptionClass(info.Kind),
+                           id, info.Name, Group, Alias, info.Param);
 
   if (info.Flags & DriverOption)
     Opt->setDriverOption(true);
diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp
dissimilarity index 69%
index 03360ea..054f7eb 100644
--- a/lib/Driver/Option.cpp
+++ b/lib/Driver/Option.cpp
@@ -1,280 +1,204 @@
-//===--- Option.cpp - Abstract Driver Options -----------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Driver/Option.h"
-
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <cassert>
-#include <algorithm>
-using namespace clang::driver;
-
-Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
-               const OptionGroup *_Group, const Option *_Alias)
-  : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
-    Unsupported(false), LinkerInput(false), NoOptAsInput(false),
-    DriverOption(false), NoArgumentUnused(false), NoForward(false) {
-
-  // Multi-level aliases are not supported, and alias options cannot
-  // have groups. This just simplifies option tracking, it is not an
-  // inherent limitation.
-  assert((!Alias || (!Alias->Alias && !Group)) &&
-         "Multi-level aliases and aliases with groups are unsupported.");
-
-  // Initialize rendering options based on the class.
-  switch (Kind) {
-  case GroupClass:
-  case InputClass:
-  case UnknownClass:
-    RenderStyle = RenderValuesStyle;
-    break;
-
-  case JoinedClass:
-  case JoinedAndSeparateClass:
-    RenderStyle = RenderJoinedStyle;
-    break;
-
-  case CommaJoinedClass:
-    RenderStyle = RenderCommaJoinedStyle;
-    break;
-
-  case FlagClass:
-  case SeparateClass:
-  case MultiArgClass:
-  case JoinedOrSeparateClass:
-    RenderStyle = RenderSeparateStyle;
-    break;
-  }
-}
-
-Option::~Option() {
-}
-
-void Option::dump() const {
-  llvm::errs() << "<";
-  switch (Kind) {
-#define P(N) case N: llvm::errs() << #N; break
-    P(GroupClass);
-    P(InputClass);
-    P(UnknownClass);
-    P(FlagClass);
-    P(JoinedClass);
-    P(SeparateClass);
-    P(CommaJoinedClass);
-    P(MultiArgClass);
-    P(JoinedOrSeparateClass);
-    P(JoinedAndSeparateClass);
-#undef P
-  }
-
-  llvm::errs() << " Name:\"" << Name << '"';
-
-  if (Group) {
-    llvm::errs() << " Group:";
-    Group->dump();
-  }
-
-  if (Alias) {
-    llvm::errs() << " Alias:";
-    Alias->dump();
-  }
-
-  if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
-    llvm::errs() << " NumArgs:" << MOA->getNumArgs();
-
-  llvm::errs() << ">\n";
-}
-
-bool Option::matches(OptSpecifier Opt) const {
-  // Aliases are never considered in matching, look through them.
-  if (Alias)
-    return Alias->matches(Opt);
-
-  // Check exact match.
-  if (ID == Opt)
-    return true;
-
-  if (Group)
-    return Group->matches(Opt);
-  return false;
-}
-
-OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
-                         const OptionGroup *Group)
-  : Option(Option::GroupClass, ID, Name, Group, 0) {
-}
-
-Arg *OptionGroup::accept(const ArgList &Args, unsigned &Index) const {
-  llvm_unreachable("accept() should never be called on an OptionGroup");
-}
-
-InputOption::InputOption(OptSpecifier ID)
-  : Option(Option::InputClass, ID, "<input>", 0, 0) {
-}
-
-Arg *InputOption::accept(const ArgList &Args, unsigned &Index) const {
-  llvm_unreachable("accept() should never be called on an InputOption");
-}
-
-UnknownOption::UnknownOption(OptSpecifier ID)
-  : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
-}
-
-Arg *UnknownOption::accept(const ArgList &Args, unsigned &Index) const {
-  llvm_unreachable("accept() should never be called on an UnknownOption");
-}
-
-FlagOption::FlagOption(OptSpecifier ID, const char *Name,
-                       const OptionGroup *Group, const Option *Alias)
-  : Option(Option::FlagClass, ID, Name, Group, Alias) {
-}
-
-Arg *FlagOption::accept(const ArgList &Args, unsigned &Index) const {
-  // Matches iff this is an exact match.
-  // FIXME: Avoid strlen.
-  if (getName().size() != strlen(Args.getArgString(Index)))
-    return 0;
-
-  return new Arg(getUnaliasedOption(), Index++);
-}
-
-JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
-                           const OptionGroup *Group, const Option *Alias)
-  : Option(Option::JoinedClass, ID, Name, Group, Alias) {
-}
-
-Arg *JoinedOption::accept(const ArgList &Args, unsigned &Index) const {
-  // Always matches.
-  const char *Value = Args.getArgString(Index) + getName().size();
-  return new Arg(getUnaliasedOption(), Index++, Value);
-}
-
-CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
-                                     const OptionGroup *Group,
-                                     const Option *Alias)
-  : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
-}
-
-Arg *CommaJoinedOption::accept(const ArgList &Args,
-                               unsigned &Index) const {
-  // Always matches.
-  const char *Str = Args.getArgString(Index) + getName().size();
-  Arg *A = new Arg(getUnaliasedOption(), Index++);
-
-  // Parse out the comma separated values.
-  const char *Prev = Str;
-  for (;; ++Str) {
-    char c = *Str;
-
-    if (!c || c == ',') {
-      if (Prev != Str) {
-        char *Value = new char[Str - Prev + 1];
-        memcpy(Value, Prev, Str - Prev);
-        Value[Str - Prev] = '\0';
-        A->getValues().push_back(Value);
-      }
-
-      if (!c)
-        break;
-
-      Prev = Str + 1;
-    }
-  }
-  A->setOwnsValues(true);
-
-  return A;
-}
-
-SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
-                               const OptionGroup *Group, const Option *Alias)
-  : Option(Option::SeparateClass, ID, Name, Group, Alias) {
-}
-
-Arg *SeparateOption::accept(const ArgList &Args, unsigned &Index) const {
-  // Matches iff this is an exact match.
-  // FIXME: Avoid strlen.
-  if (getName().size() != strlen(Args.getArgString(Index)))
-    return 0;
-
-  Index += 2;
-  if (Index > Args.getNumInputArgStrings())
-    return 0;
-
-  return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
-}
-
-MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
-                               const OptionGroup *Group, const Option *Alias,
-                               unsigned _NumArgs)
-  : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
-  assert(NumArgs > 1  && "Invalid MultiArgOption!");
-}
-
-Arg *MultiArgOption::accept(const ArgList &Args, unsigned &Index) const {
-  // Matches iff this is an exact match.
-  // FIXME: Avoid strlen.
-  if (getName().size() != strlen(Args.getArgString(Index)))
-    return 0;
-
-  Index += 1 + NumArgs;
-  if (Index > Args.getNumInputArgStrings())
-    return 0;
-
-  Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
-                   Args.getArgString(Index - NumArgs));
-  for (unsigned i = 1; i != NumArgs; ++i)
-    A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
-  return A;
-}
-
-JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID,
-                                               const char *Name,
-                                               const OptionGroup *Group,
-                                               const Option *Alias)
-  : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
-}
-
-Arg *JoinedOrSeparateOption::accept(const ArgList &Args,
-                                    unsigned &Index) const {
-  // If this is not an exact match, it is a joined arg.
-  // FIXME: Avoid strlen.
-  if (getName().size() != strlen(Args.getArgString(Index))) {
-    const char *Value = Args.getArgString(Index) + getName().size();
-    return new Arg(this, Index++, Value);
-  }
-
-  // Otherwise it must be separate.
-  Index += 2;
-  if (Index > Args.getNumInputArgStrings())
-    return 0;
-
-  return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
-}
-
-JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
-                                                 const char *Name,
-                                                 const OptionGroup *Group,
-                                                 const Option *Alias)
-  : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
-}
-
-Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
-                                     unsigned &Index) const {
-  // Always matches.
-
-  Index += 2;
-  if (Index > Args.getNumInputArgStrings())
-    return 0;
-
-  return new Arg(getUnaliasedOption(), Index - 2,
-                 Args.getArgString(Index-2)+getName().size(),
-                 Args.getArgString(Index-1));
-}
+//===--- Option.cpp - Abstract Driver Options -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Option.h"
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <algorithm>
+using namespace clang::driver;
+
+Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
+               const Option *_Group, const Option *_Alias, unsigned Args)
+  : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
+    NumArgs(Args), Unsupported(false), LinkerInput(false), NoOptAsInput(false),
+    DriverOption(false), NoArgumentUnused(false), NoForward(false) {
+
+  // Multi-level aliases are not supported, and alias options cannot
+  // have groups. This just simplifies option tracking, it is not an
+  // inherent limitation.
+  assert((!Alias || (!Alias->Alias && !Group)) &&
+         "Multi-level aliases and aliases with groups are unsupported.");
+
+  // Initialize rendering options based on the class.
+  switch (Kind) {
+  case GroupClass:
+  case InputClass:
+  case UnknownClass:
+    RenderStyle = RenderValuesStyle;
+    break;
+
+  case JoinedClass:
+  case JoinedAndSeparateClass:
+    RenderStyle = RenderJoinedStyle;
+    break;
+
+  case CommaJoinedClass:
+    RenderStyle = RenderCommaJoinedStyle;
+    break;
+
+  case FlagClass:
+  case SeparateClass:
+  case MultiArgClass:
+  case JoinedOrSeparateClass:
+    RenderStyle = RenderSeparateStyle;
+    break;
+  }
+}
+
+Option::~Option() {
+}
+
+void Option::dump() const {
+  llvm::errs() << "<";
+  switch (Kind) {
+#define P(N) case N: llvm::errs() << #N; break
+    P(GroupClass);
+    P(InputClass);
+    P(UnknownClass);
+    P(FlagClass);
+    P(JoinedClass);
+    P(SeparateClass);
+    P(CommaJoinedClass);
+    P(MultiArgClass);
+    P(JoinedOrSeparateClass);
+    P(JoinedAndSeparateClass);
+#undef P
+  }
+
+  llvm::errs() << " Name:\"" << Name << '"';
+
+  if (Group) {
+    llvm::errs() << " Group:";
+    Group->dump();
+  }
+
+  if (Alias) {
+    llvm::errs() << " Alias:";
+    Alias->dump();
+  }
+
+  if (Kind == MultiArgClass)
+    llvm::errs() << " NumArgs:" << NumArgs;
+
+  llvm::errs() << ">\n";
+}
+
+bool Option::matches(OptSpecifier Opt) const {
+  // Aliases are never considered in matching, look through them.
+  if (Alias)
+    return Alias->matches(Opt);
+
+  // Check exact match.
+  if (ID == Opt)
+    return true;
+
+  if (Group)
+    return Group->matches(Opt);
+  return false;
+}
+
+Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
+  switch (Kind) {
+  case FlagClass:
+    if (getName().size() != strlen(Args.getArgString(Index)))
+      return 0;
+
+    return new Arg(getUnaliasedOption(), Index++);
+  case JoinedClass: {
+    const char *Value = Args.getArgString(Index) + getName().size();
+    return new Arg(getUnaliasedOption(), Index++, Value);
+  }
+  case CommaJoinedClass: {
+    // Always matches.
+    const char *Str = Args.getArgString(Index) + getName().size();
+    Arg *A = new Arg(getUnaliasedOption(), Index++);
+
+    // Parse out the comma separated values.
+    const char *Prev = Str;
+    for (;; ++Str) {
+      char c = *Str;
+
+      if (!c || c == ',') {
+        if (Prev != Str) {
+          char *Value = new char[Str - Prev + 1];
+          memcpy(Value, Prev, Str - Prev);
+          Value[Str - Prev] = '\0';
+          A->getValues().push_back(Value);
+        }
+
+        if (!c)
+          break;
+
+        Prev = Str + 1;
+      }
+    }
+    A->setOwnsValues(true);
+
+    return A;
+  }
+  case SeparateClass:
+    // Matches iff this is an exact match.
+    // FIXME: Avoid strlen.
+    if (getName().size() != strlen(Args.getArgString(Index)))
+      return 0;
+
+    Index += 2;
+    if (Index > Args.getNumInputArgStrings())
+      return 0;
+
+    return new Arg(getUnaliasedOption(),
+                   Index - 2, Args.getArgString(Index - 1));
+  case MultiArgClass: {
+    // Matches iff this is an exact match.
+    // FIXME: Avoid strlen.
+    if (getName().size() != strlen(Args.getArgString(Index)))
+      return 0;
+
+    Index += 1 + NumArgs;
+    if (Index > Args.getNumInputArgStrings())
+      return 0;
+
+    Arg *A = new Arg(getUnaliasedOption(), Index - 1 - NumArgs,
+                      Args.getArgString(Index - NumArgs));
+    for (unsigned i = 1; i != NumArgs; ++i)
+      A->getValues().push_back(Args.getArgString(Index - NumArgs + i));
+    return A;
+  }
+  case JoinedOrSeparateClass: {
+    // If this is not an exact match, it is a joined arg.
+    // FIXME: Avoid strlen.
+    if (getName().size() != strlen(Args.getArgString(Index))) {
+      const char *Value = Args.getArgString(Index) + getName().size();
+      return new Arg(this, Index++, Value);
+    }
+
+    // Otherwise it must be separate.
+    Index += 2;
+    if (Index > Args.getNumInputArgStrings())
+      return 0;
+
+    return new Arg(getUnaliasedOption(),
+                   Index - 2, Args.getArgString(Index - 1));
+  }
+  case JoinedAndSeparateClass:
+    // Always matches.
+    Index += 2;
+    if (Index > Args.getNumInputArgStrings())
+      return 0;
+
+    return new Arg(getUnaliasedOption(), Index - 2,
+                   Args.getArgString(Index-2)+getName().size(),
+                   Args.getArgString(Index-1));
+  }
+  llvm_unreachable("Invalid option kind!");
+}
-- 
1.7.10.msysgit.1

