+//===----------------------------------------------------------------------===//
+// OptionValue class
+
+// Support value comparison outside the template.
+struct GenericOptionValue {
+ virtual ~GenericOptionValue() {}
+ virtual bool compare(const GenericOptionValue &V) const = 0;
+private:
+ virtual void anchor();
+};
+
+template<class DataType> struct OptionValue;
+
+// The default value safely does nothing. Option value printing is only
+// best-effort.
+template<class DataType, bool isClass>
+struct OptionValueBase : public GenericOptionValue {
+ // Temporary storage for argument passing.
+ typedef OptionValue<DataType> WrapperType;
+
+ bool hasValue() const { return false; }
+
+ const DataType &getValue() const { llvm_unreachable("no default value"); }
+
+ // Some options may take their value from a different data type.
+ template<class DT>
+ void setValue(const DT& /*V*/) {}
+
+ bool compare(const DataType &/*V*/) const { return false; }
+
+ virtual bool compare(const GenericOptionValue& /*V*/) const { return false; }
+};
+
+// Simple copy of the option value.
+template<class DataType>
+class OptionValueCopy : public GenericOptionValue {
+ DataType Value;
+ bool Valid;
+public:
+ OptionValueCopy() : Valid(false) {}
+
+ bool hasValue() const { return Valid; }
+
+ const DataType &getValue() const {
+ assert(Valid && "invalid option value");
+ return Value;
+ }
+
+ void setValue(const DataType &V) { Valid = true; Value = V; }
+
+ bool compare(const DataType &V) const {
+ return Valid && (Value != V);
+ }
+
+ virtual bool compare(const GenericOptionValue &V) const {
+ const OptionValueCopy<DataType> &VC =
+ static_cast< const OptionValueCopy<DataType>& >(V);
+ if (!VC.hasValue()) return false;
+ return compare(VC.getValue());
+ }
+};
+
+// Non-class option values.
+template<class DataType>
+struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> {
+ typedef DataType WrapperType;
+};
+
+// Top-level option class.
+template<class DataType>
+struct OptionValue : OptionValueBase<DataType, is_class<DataType>::value> {
+ OptionValue() {}
+
+ OptionValue(const DataType& V) {
+ this->setValue(V);
+ }
+ // Some options may take their value from a different data type.
+ template<class DT>
+ OptionValue<DataType> &operator=(const DT& V) {
+ this->setValue(V);
+ return *this;
+ }
+};
+
+// Other safe-to-copy-by-value common option types.
+enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
+template<>
+struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> {
+ typedef cl::boolOrDefault WrapperType;
+
+ OptionValue() {}
+
+ OptionValue(const cl::boolOrDefault& V) {
+ this->setValue(V);
+ }
+ OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault& V) {
+ setValue(V);
+ return *this;
+ }
+private:
+ virtual void anchor();
+};
+
+template<>
+struct OptionValue<std::string> : OptionValueCopy<std::string> {
+ typedef StringRef WrapperType;
+
+ OptionValue() {}
+
+ OptionValue(const std::string& V) {
+ this->setValue(V);
+ }
+ OptionValue<std::string> &operator=(const std::string& V) {
+ setValue(V);
+ return *this;
+ }
+private:
+ virtual void anchor();
+};
+