Make Option non virtual.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162231 91177308-0d34-0410-b5e6-96231b3b80d8
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 driver {
   class Arg;
   class ArgList;
-  class OptionGroup;
 
   /// Option - Abstract representation for a single form of driver
   /// argument.
@@ -63,11 +62,13 @@
     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 @@
     /// 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 @@
     /// 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 @@
        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 @@
       // 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 @@
 
 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
index 03360ea..054f7eb 100644
--- a/lib/Driver/Option.cpp
+++ b/lib/Driver/Option.cpp
@@ -18,9 +18,9 @@
 using namespace clang::driver;
 
 Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
-               const OptionGroup *_Group, const Option *_Alias)
+               const Option *_Group, const Option *_Alias, unsigned Args)
   : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
-    Unsupported(false), LinkerInput(false), NoOptAsInput(false),
+    NumArgs(Args), Unsupported(false), LinkerInput(false), NoOptAsInput(false),
     DriverOption(false), NoArgumentUnused(false), NoForward(false) {
 
   // Multi-level aliases are not supported, and alias options cannot
@@ -87,8 +87,8 @@
     Alias->dump();
   }
 
-  if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
-    llvm::errs() << " NumArgs:" << MOA->getNumArgs();
+  if (Kind == MultiArgClass)
+    llvm::errs() << " NumArgs:" << NumArgs;
 
   llvm::errs() << ">\n";
 }
@@ -107,174 +107,98 @@
   return false;
 }
 
-OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
-                         const OptionGroup *Group)
-  : Option(Option::GroupClass, ID, Name, Group, 0) {
-}
+Arg *Option::accept(const ArgList &Args, unsigned &Index) const {
+  switch (Kind) {
+  case FlagClass:
+    if (getName().size() != strlen(Args.getArgString(Index)))
+      return 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))) {
+    return new Arg(getUnaliasedOption(), Index++);
+  case JoinedClass: {
     const char *Value = Args.getArgString(Index) + getName().size();
-    return new Arg(this, Index++, Value);
+    return new Arg(getUnaliasedOption(), Index++, Value);
   }
+  case CommaJoinedClass: {
+    // Always matches.
+    const char *Str = Args.getArgString(Index) + getName().size();
+    Arg *A = new Arg(getUnaliasedOption(), Index++);
 
-  // Otherwise it must be separate.
-  Index += 2;
-  if (Index > Args.getNumInputArgStrings())
-    return 0;
+    // Parse out the comma separated values.
+    const char *Prev = Str;
+    for (;; ++Str) {
+      char c = *Str;
 
-  return new Arg(getUnaliasedOption(), Index - 2, Args.getArgString(Index - 1));
-}
+      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);
+        }
 
-JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
-                                                 const char *Name,
-                                                 const OptionGroup *Group,
-                                                 const Option *Alias)
-  : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
-}
+        if (!c)
+          break;
 
-Arg *JoinedAndSeparateOption::accept(const ArgList &Args,
-                                     unsigned &Index) const {
-  // Always matches.
+        Prev = Str + 1;
+      }
+    }
+    A->setOwnsValues(true);
 
-  Index += 2;
-  if (Index > Args.getNumInputArgStrings())
-    return 0;
+    return A;
+  }
+  case SeparateClass:
+    // Matches iff this is an exact match.
+    // FIXME: Avoid strlen.
+    if (getName().size() != strlen(Args.getArgString(Index)))
+      return 0;
 
-  return new Arg(getUnaliasedOption(), Index - 2,
-                 Args.getArgString(Index-2)+getName().size(),
-                 Args.getArgString(Index-1));
+    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!");
 }