blob: 8243f6d69314bbf1aac7a71e695ea2d177f3829f [file] [log] [blame]
//===--- Option.h - Abstract Driver Options ---------------------*- 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_OPTION_H_
#define CLANG_DRIVER_OPTION_H_
#include "clang/Driver/OptSpecifier.h"
#include "llvm/ADT/StringRef.h"
#include "clang/Basic/LLVM.h"
namespace clang {
namespace driver {
class Arg;
class ArgList;
class OptionGroup;
/// Option - Abstract representation for a single form of driver
/// argument.
///
/// An Option class represents a form of option that the driver
/// takes, for example how many arguments the option has and how
/// they can be provided. Individual option instances store
/// additional information about what group the option is a member
/// of (if any), if the option is an alias, and a number of
/// flags. At runtime the driver parses the command line into
/// concrete Arg instances, each of which corresponds to a
/// particular Option instance.
class Option {
public:
enum OptionClass {
GroupClass = 0,
InputClass,
UnknownClass,
FlagClass,
JoinedClass,
SeparateClass,
CommaJoinedClass,
MultiArgClass,
JoinedOrSeparateClass,
JoinedAndSeparateClass
};
enum RenderStyleKind {
RenderCommaJoinedStyle,
RenderJoinedStyle,
RenderSeparateStyle,
RenderValuesStyle
};
private:
OptionClass Kind;
/// The option ID.
OptSpecifier ID;
/// The option name.
StringRef Name;
/// Group this option is a member of, if any.
const OptionGroup *Group;
/// Option that this is an alias for, if any.
const Option *Alias;
/// Unsupported options will be rejected.
bool Unsupported : 1;
/// Treat this option like a linker input?
bool LinkerInput : 1;
/// When rendering as an input, don't render the option.
// FIXME: We should ditch the render/renderAsInput distinction.
bool NoOptAsInput : 1;
/// The style to using when rendering arguments parsed by this option.
unsigned RenderStyle : 2;
/// This option is only consumed by the driver.
bool DriverOption : 1;
/// This option should not report argument unused errors.
bool NoArgumentUnused : 1;
/// This option should not be implicitly forwarded.
bool NoForward : 1;
protected:
Option(OptionClass Kind, OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias);
public:
virtual ~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 *getAlias() const { return Alias; }
bool isUnsupported() const { return Unsupported; }
void setUnsupported(bool Value) { Unsupported = Value; }
bool isLinkerInput() const { return LinkerInput; }
void setLinkerInput(bool Value) { LinkerInput = Value; }
bool hasNoOptAsInput() const { return NoOptAsInput; }
void setNoOptAsInput(bool Value) { NoOptAsInput = Value; }
RenderStyleKind getRenderStyle() const {
return RenderStyleKind(RenderStyle);
}
void setRenderStyle(RenderStyleKind Value) { RenderStyle = Value; }
bool isDriverOption() const { return DriverOption; }
void setDriverOption(bool Value) { DriverOption = Value; }
bool hasNoArgumentUnused() const { return NoArgumentUnused; }
void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; }
bool hasNoForward() const { return NoForward; }
void setNoForward(bool Value) { NoForward = Value; }
bool hasForwardToGCC() const {
return !NoForward && !DriverOption && !LinkerInput;
}
/// getUnaliasedOption - Return the final option this option
/// aliases (itself, if the option has no alias).
const Option *getUnaliasedOption() const {
if (Alias) return Alias->getUnaliasedOption();
return this;
}
/// getRenderName - Return the name to use when rendering this
/// option.
StringRef getRenderName() const {
return getUnaliasedOption()->getName();
}
/// matches - Predicate for whether this option is part of the
/// given option (which may be a group).
///
/// Note that matches against options which are an alias should never be
/// done -- aliases do not participate in matching and so such a query will
/// always be false.
bool matches(OptSpecifier ID) const;
/// accept - Potentially accept the current argument, returning a
/// new Arg instance, or 0 if the option does not accept this
/// argument (or the argument is missing values).
///
/// 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;
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
} // end namespace clang
#endif