#ifndef CLANG_DRIVER_OPTION_H_
#define CLANG_DRIVER_OPTION_H_
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
namespace clang {
namespace driver {
class Arg;
class Option {
public:
enum OptionClass {
- GroupOption = 0,
- InputOption,
- UnknownOption,
- FlagOption,
- JoinedOption,
- SeparateOption,
- CommaJoinedOption,
- MultiArgOption,
- JoinedOrSeparateOption,
- JoinedAndSeparateOption
+ GroupClass = 0,
+ InputClass,
+ UnknownClass,
+ FlagClass,
+ JoinedClass,
+ SeparateClass,
+ CommaJoinedClass,
+ MultiArgClass,
+ JoinedOrSeparateClass,
+ JoinedAndSeparateClass
};
private:
protected:
Option(OptionClass Kind, const char *Name,
- OptionGroup *Group, Option *Alias);
+ const OptionGroup *Group, const Option *Alias);
public:
virtual ~Option();
///
/// May issue a missing argument error.
virtual Arg *accept(ArgList &Args, unsigned Index) const = 0;
+
+ 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 {
- OptionGroup *Group;
-
public:
- OptionGroup(const char *Name, OptionGroup *Group);
+ OptionGroup(const char *Name, const OptionGroup *Group);
virtual Arg *accept(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();
virtual Arg *accept(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.
UnknownOption();
virtual Arg *accept(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(const char *Name, OptionGroup *Group, Option *Alias);
+ FlagOption(const char *Name, const OptionGroup *Group, const Option *Alias);
virtual Arg *accept(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 {
- JoinedOption(const char *Name, OptionGroup *Group, Option *Alias);
+ public:
+ JoinedOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias);
virtual Arg *accept(ArgList &Args, unsigned Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::JoinedClass;
+ }
+ static bool classof(const JoinedOption *) { return true; }
};
- class CommaJoinedOption : public Option {
- CommaJoinedOption(const char *Name, OptionGroup *Group, Option *Alias);
+ class SeparateOption : public Option {
+ public:
+ SeparateOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias);
virtual Arg *accept(ArgList &Args, unsigned Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::SeparateClass;
+ }
+ static bool classof(const SeparateOption *) { return true; }
};
- class SeparateOption : public Option {
- SeparateOption(const char *Name, OptionGroup *Group, Option *Alias);
+ class CommaJoinedOption : public Option {
+ public:
+ CommaJoinedOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias);
virtual Arg *accept(ArgList &Args, unsigned Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::CommaJoinedClass;
+ }
+ static bool classof(const CommaJoinedOption *) { return true; }
};
/// MultiArgOption - An option which takes multiple arguments (these
unsigned NumArgs;
public:
- MultiArgOption(const char *Name, OptionGroup *Group, Option *Alias,
- unsigned NumArgs);
+ MultiArgOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias, unsigned NumArgs);
unsigned getNumArgs() const { return NumArgs; }
virtual Arg *accept(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 {
- JoinedOrSeparateOption(const char *Name, OptionGroup *Group, Option *Alias);
+ public:
+ JoinedOrSeparateOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias);
virtual Arg *accept(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 {
- JoinedAndSeparateOption(const char *Name, OptionGroup *Group, Option *Alias);
+ public:
+ JoinedAndSeparateOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias);
virtual Arg *accept(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
--- /dev/null
+//===--- Options.def - Driver option info -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the driver option information. Users of this file
+// must define the OPTION macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OPTION
+#error "Define OPTION prior to including this file!"
+#endif
+
+// OPTION(ID, KIND, NAME, GROUP, ALIAS, FLAGS, PARAM)
+
+// The first value provided to the macro specifies the internal name
+// of the option, and results in a clang::driver::options::XX enum
+// value for XX.
+
+// The second value is the option type, one of Group, Flag, Joined,
+// Separate, CommaJoined, JoinedOrSeparate, JoinedAndSeparate.
+
+// The third value is the option name.
+
+// The fourth value is the internal name of the option group, or 0 if
+// the option is not part of a group.
+
+// The fifth value is the internal name of an aliased option, or 0 if
+// the option is not an alias.
+
+// The sixth value is a string containing option flags. Valid values:
+// l: The option is a linker input.
+//
+// i: The option should not render the name when rendered as an
+// input.
+//
+// S: The option should be rendered separately, even if joined (only
+// sensible on joined options).
+//
+// J: The option should be rendered joined, even if separate (only
+// sensible on single value separate options).
+//
+// U: The option is unsupported, and the driver will reject command
+// lines that use it.
+
+/// The seventh value is an arbitrary integer parameter; currently
+/// this is only used for specifying the number of arguments for
+/// Separate options.
+
+OPTION(ArchOpt, Separate, "-arch", 0, 0, "", 0)
+OPTION(PassExitCodesFlag, Flag, "-pass-exit-codes", 0, 0, "", 0)
+OPTION(PrintFileNameOpt, Joined, "-print-file-name=", 0, 0, "", 0)
--- /dev/null
+//===--- Options.h - Option info & table ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_OPTIONS_H_
+#define CLANG_DRIVER_OPTIONS_H_
+
+namespace clang {
+namespace driver {
+namespace options {
+ enum ID {
+ NotOption = 0, // This is not an option ID.
+#define OPTION(ID, KIND, NAME, GROUP, ALIAS, FLAGS, PARAM) ID,
+#include "clang/Driver/Options.def"
+ LastOption
+#undef OPTION
+ };
+}
+
+ class Option;
+
+ /// OptTable - Provide access to the Option info table.
+ ///
+ /// The OptTable class provides a layer of indirection which allows
+ /// Option instance to be created lazily. In the common case, only a
+ /// few options will be needed at runtime; the OptTable class
+ /// maintains enough information to parse command lines without
+ /// instantiating Options, while letting other parts of the driver
+ /// still use Option instances where convient.
+ class OptTable {
+ mutable Option **Options;
+
+ Option *constructOption(options::ID id) const;
+
+ public:
+ OptTable();
+ ~OptTable();
+
+ unsigned getNumOptions() const;
+
+ const char *getOptionName(options::ID id) const;
+
+ /// getOption - Get the given \arg id's Option instance, lazily
+ /// creating it if necessary.
+ const Option *getOption(options::ID id) const;
+ };
+}
+}
+
+#endif
--- /dev/null
+//===--- Options.cpp - Option info table --------------------------------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Options.h"
+
+#include "clang/Driver/Option.h"
+#include <cassert>
+
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+
+struct Info {
+ Option::OptionClass Kind;
+ const char *Name;
+ unsigned GroupID;
+ unsigned AliasID;
+ const char *Flags;
+ unsigned Param;
+};
+
+static Info OptionInfos[] = {
+#define OPTION(ID, KIND, NAME, GROUP, ALIAS, FLAGS, PARAM) \
+ { Option::KIND##Class, NAME, GROUP, ALIAS, FLAGS, PARAM },
+#include "clang/Driver/Options.def"
+};
+static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]);
+
+static Info &getInfo(unsigned id) {
+ assert(id > 0 && id - 1 < numOptions && "Invalid Option ID.");
+ return OptionInfos[id - 1];
+}
+
+OptTable::OptTable() : Options(new Option*[numOptions]) {
+}
+
+OptTable::~OptTable() {
+ for (unsigned i=0; i<numOptions; ++i)
+ delete Options[i];
+ delete[] Options;
+}
+
+unsigned OptTable::getNumOptions() const {
+ return numOptions;
+}
+
+const char *OptTable::getOptionName(options::ID id) const {
+ return getInfo(id).Name;
+}
+
+const Option *OptTable::getOption(options::ID id) const {
+ if (id == 0)
+ return 0;
+
+ assert((unsigned) (id - 1) < numOptions && "Invalid ID.");
+
+ Option *&Entry = Options[id - 1];
+ if (!Entry)
+ Entry = constructOption(id);
+
+ return Entry;
+}
+
+Option *OptTable::constructOption(options::ID id) const {
+ Info &info = getInfo(id);
+ const OptionGroup *Group =
+ cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
+ const Option *Alias = getOption((options::ID) info.AliasID);
+
+ Option *Opt = 0;
+ switch (info.Kind) {
+ default:
+ assert(0 && "Invalid option kind.");
+ case Option::GroupClass:
+ Opt = new OptionGroup(info.Name, Group); break;
+ case Option::FlagClass:
+ Opt = new FlagOption(info.Name, Group, Alias); break;
+ case Option::JoinedClass:
+ Opt = new JoinedOption(info.Name, Group, Alias); break;
+ case Option::SeparateClass:
+ Opt = new SeparateOption(info.Name, Group, Alias); break;
+ case Option::CommaJoinedClass:
+ Opt = new CommaJoinedOption(info.Name, Group, Alias); break;
+ case Option::MultiArgClass:
+ Opt = new MultiArgOption(info.Name, Group, Alias, info.Param); break;
+ case Option::JoinedOrSeparateClass:
+ Opt = new JoinedOrSeparateOption(info.Name, Group, Alias); break;
+ case Option::JoinedAndSeparateClass:
+ Opt = new JoinedAndSeparateOption(info.Name, Group, Alias); break;
+ }
+
+ // FIXME: Set flags.
+ for (const char *s = info.Flags; *s; ++s) {
+ switch (*s) {
+ default:
+ assert(0 && "Invalid option flag.");
+ case 'l':
+ break;
+ case 'i':
+ break;
+ case 'J':
+ break;
+ case 'S':
+ break;
+ case 'U':
+ break;
+ }
+ }
+
+ return Opt;
+}
//===----------------------------------------------------------------------===//
#include "clang/Driver/Option.h"
+#include "llvm/Support/raw_ostream.h"
#include <cassert>
using namespace clang;
using namespace clang::driver;
Option::Option(OptionClass _Kind, const char *_Name,
- OptionGroup *_Group, Option *_Alias)
+ const OptionGroup *_Group, const Option *_Alias)
: Kind(_Kind), Name(_Name), Group(_Group), Alias(_Alias) {
// Multi-level aliases are not supported, and alias options cannot
"Multi-level aliases and aliases with groups are unsupported.");
}
+Option::~Option() {
+}
+
+void Option::dump() const {
+ llvm::errs() << "<";
+ switch (Kind) {
+ default:
+ assert(0 && "Invalid 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(const Option *Opt) const {
// Aliases are never considered in matching.
if (Opt->getAlias())
return false;
}
-OptionGroup::OptionGroup(const char *Name, OptionGroup *Group)
- : Option(Option::GroupOption, Name, Group, 0) {
+OptionGroup::OptionGroup(const char *Name, const OptionGroup *Group)
+ : Option(Option::GroupClass, Name, Group, 0) {
+}
+
+Arg *OptionGroup::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
}
InputOption::InputOption()
- : Option(Option::InputOption, "<input>", 0, 0) {
+ : Option(Option::InputClass, "<input>", 0, 0) {
+}
+
+Arg *InputOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
}
UnknownOption::UnknownOption()
- : Option(Option::UnknownOption, "<unknown>", 0, 0) {
+ : Option(Option::UnknownClass, "<unknown>", 0, 0) {
}
-FlagOption::FlagOption(const char *Name, OptionGroup *Group, Option *Alias)
- : Option(Option::FlagOption, Name, Group, Alias) {
+Arg *UnknownOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
}
+FlagOption::FlagOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::FlagClass, Name, Group, Alias) {
+}
-JoinedOption::JoinedOption(const char *Name, OptionGroup *Group, Option *Alias)
- : Option(Option::JoinedOption, Name, Group, Alias) {
+Arg *FlagOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
}
-CommaJoinedOption::CommaJoinedOption(const char *Name, OptionGroup *Group,
- Option *Alias)
- : Option(Option::CommaJoinedOption, Name, Group, Alias) {
+JoinedOption::JoinedOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::JoinedClass, Name, Group, Alias) {
}
-SeparateOption::SeparateOption(const char *Name, OptionGroup *Group,
- Option *Alias)
- : Option(Option::SeparateOption, Name, Group, Alias) {
+Arg *JoinedOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
}
-MultiArgOption::MultiArgOption(const char *Name, OptionGroup *Group,
- Option *Alias, unsigned _NumArgs)
- : Option(Option::MultiArgOption, Name, Group, Alias), NumArgs(_NumArgs) {
+CommaJoinedOption::CommaJoinedOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::CommaJoinedClass, Name, Group, Alias) {
+}
+
+Arg *CommaJoinedOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
+}
+
+SeparateOption::SeparateOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::SeparateClass, Name, Group, Alias) {
+}
+
+Arg *SeparateOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
+}
+
+MultiArgOption::MultiArgOption(const char *Name, const OptionGroup *Group,
+ const Option *Alias, unsigned _NumArgs)
+ : Option(Option::MultiArgClass, Name, Group, Alias), NumArgs(_NumArgs) {
+}
+
+Arg *MultiArgOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
}
JoinedOrSeparateOption::JoinedOrSeparateOption(const char *Name,
- OptionGroup *Group,
- Option *Alias)
- : Option(Option::JoinedOrSeparateOption, Name, Group, Alias) {
+ const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::JoinedOrSeparateClass, Name, Group, Alias) {
+}
+
+Arg *JoinedOrSeparateOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
}
JoinedAndSeparateOption::JoinedAndSeparateOption(const char *Name,
- OptionGroup *Group,
- Option *Alias)
- : Option(Option::JoinedAndSeparateOption, Name, Group, Alias) {
+ const OptionGroup *Group,
+ const Option *Alias)
+ : Option(Option::JoinedAndSeparateClass, Name, Group, Alias) {
}
+Arg *JoinedAndSeparateOption::accept(ArgList &Args, unsigned Index) const {
+ assert(0 && "FIXME");
+ return 0;
+}
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include
CXXFLAGS = -fno-rtti
-LINK_COMPONENTS := system
+LINK_COMPONENTS := system support
USEDLIBS = clangDriver.a
# This tool has no plugins, optimize startup time.
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+
#include "llvm/ADT/OwningPtr.h"
#include "llvm/System/Signals.h"
using namespace clang;