diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index c4bcb970094..815cb783abc 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -66,176 +66,183 @@ debug (const Value_Range &r)
   fprintf (stderr, "\n");
 }
 
-// Default implementation when none has been defined.
+// Default vrange definitions.
 
 bool
 vrange::contains_p (tree) const
 {
-  return false;
+  return varying_p ();
 }
 
-// Default implementation when none has been defined.
-
 bool
 vrange::singleton_p (tree *) const
 {
   return false;
 }
 
-// Assignment operator for generic ranges.  Copying incompatible types
-// is not allowed.
-
-vrange &
-vrange::operator= (const vrange &src)
+void
+vrange::set (tree, tree, value_range_kind)
 {
-  if (is_a <irange> (src))
-    {
-      as_a <irange> (*this) = as_a <irange> (src);
-      return *this;
-    }
-  else
-    gcc_unreachable ();
 }
 
-// Equality operator for generic ranges.
-
-bool
-vrange::operator== (const vrange &src) const
+tree
+vrange::type () const
 {
-  if (is_a <irange> (src))
-    return as_a <irange> (*this) == as_a <irange> (src);
-  gcc_unreachable ();
+  return void_type_node;
 }
 
 bool
-irange::supports_type_p (tree type) const
+vrange::supports_type_p (tree) const
 {
-  return supports_p (type);
+  return false;
 }
 
-// Return TRUE if R fits in THIS.
-
-bool
-irange::fits_p (const vrange &r) const
+void
+vrange::set_undefined ()
 {
-  return m_max_ranges >= as_a <irange> (r).num_pairs ();
+  m_kind = VR_UNDEFINED;
 }
 
 void
-irange::set_nonnegative (tree type)
+vrange::set_varying (tree)
 {
-  set (build_int_cst (type, 0), TYPE_MAX_VALUE (type));
+  m_kind = VR_VARYING;
 }
 
-unsupported_range::unsupported_range ()
+bool
+vrange::union_ (const vrange &r)
 {
-  m_discriminator = VR_UNKNOWN;
-  set_undefined ();
+  if (r.undefined_p () || varying_p ())
+    return false;
+  if (undefined_p () || r.varying_p ())
+    {
+      operator= (r);
+      return true;
+    }
+  gcc_unreachable ();
+  return false;
 }
 
-void
-unsupported_range::set (tree, tree, value_range_kind)
+bool
+vrange::intersect (const vrange &r)
 {
+  if (undefined_p () || r.varying_p ())
+    return false;
+  if (r.undefined_p ())
+    {
+      set_undefined ();
+      return true;
+    }
+  if (varying_p ())
+    {
+      operator= (r);
+      return true;
+    }
   gcc_unreachable ();
+  return false;
 }
 
-tree
-unsupported_range::type () const
+bool
+vrange::zero_p () const
 {
-  gcc_unreachable ();
-  return nullptr;
+  return false;
 }
 
 bool
-unsupported_range::supports_type_p (tree) const
+vrange::nonzero_p () const
 {
   return false;
 }
 
 void
-unsupported_range::set_undefined ()
+vrange::set_nonzero (tree)
 {
-  m_kind = VR_UNDEFINED;
 }
 
 void
-unsupported_range::set_varying (tree)
+vrange::set_zero (tree)
 {
-  gcc_unreachable ();
 }
 
 void
-unsupported_range::dump (FILE *file) const
+vrange::set_nonnegative (tree)
 {
-  fprintf (file, "[unsupported_range] ");
-  if (undefined_p ())
-    {
-      fprintf (file, "UNDEFINED");
-      return;
-    }
-  if (varying_p ())
-    {
-      fprintf (file, "VARYING");
-      return;
-    }
-  gcc_unreachable ();
 }
 
 bool
-unsupported_range::union_ (const vrange &)
+vrange::fits_p (const vrange &) const
 {
-  gcc_unreachable ();
-  return false;
+  return true;
 }
 
-bool
-unsupported_range::intersect (const vrange &)
+// Assignment operator for generic ranges.  Copying incompatible types
+// is not allowed.
+
+vrange &
+vrange::operator= (const vrange &src)
 {
-  gcc_unreachable ();
-  return false;
+  if (is_a <irange> (src))
+    {
+      as_a <irange> (*this) = as_a <irange> (src);
+      return *this;
+    }
+  else
+    gcc_unreachable ();
 }
 
+// Equality operator for generic ranges.
+
 bool
-unsupported_range::zero_p () const
+vrange::operator== (const vrange &src) const
 {
+  if (is_a <irange> (src))
+    return as_a <irange> (*this) == as_a <irange> (src);
   gcc_unreachable ();
-  return false;
 }
 
 bool
-unsupported_range::nonzero_p () const
+irange::supports_type_p (tree type) const
 {
-  gcc_unreachable ();
-  return false;
+  return supports_p (type);
 }
 
-void
-unsupported_range::set_nonzero (tree)
+// Return TRUE if R fits in THIS.
+
+bool
+irange::fits_p (const vrange &r) const
 {
-  gcc_unreachable ();
+  return m_max_ranges >= as_a <irange> (r).num_pairs ();
 }
 
 void
-unsupported_range::set_zero (tree)
+irange::set_nonnegative (tree type)
 {
-  gcc_unreachable ();
+  set (build_int_cst (type, 0), TYPE_MAX_VALUE (type));
 }
 
-void
-unsupported_range::set_nonnegative (tree)
+unsupported_range::unsupported_range ()
 {
-  gcc_unreachable ();
+  m_discriminator = VR_UNKNOWN;
+  set_undefined ();
 }
 
-bool
-unsupported_range::fits_p (const vrange &) const
+void
+unsupported_range::dump (FILE *file) const
 {
+  fprintf (file, "[unsupported_range] ");
+  if (undefined_p ())
+    {
+      fprintf (file, "UNDEFINED");
+      return;
+    }
+  if (varying_p ())
+    {
+      fprintf (file, "VARYING");
+      return;
+    }
   gcc_unreachable ();
-  return false;
 }
 
-unsupported_range Value_Range::m_unsupported;
-
 // Here we copy between any two irange's.  The ranges can be legacy or
 // multi-ranges, and copying between any combination works correctly.
 
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 69cf6c304d6..61e6a1887d5 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -73,22 +73,22 @@ class vrange
   template <typename T> friend bool is_a (vrange &);
   friend class Value_Range;
 public:
-  virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0;
-  virtual tree type () const = 0;
-  virtual bool supports_type_p (tree type) const = 0;
-  virtual void set_varying (tree type) = 0;
-  virtual void set_undefined () = 0;
+  virtual void set (tree, tree, value_range_kind = VR_RANGE);
+  virtual tree type () const;
+  virtual bool supports_type_p (tree type) const;
+  virtual void set_varying (tree type);
+  virtual void set_undefined ();
   virtual void dump (FILE * = stderr) const = 0;
-  virtual bool union_ (const vrange &) = 0;
-  virtual bool intersect (const vrange &) = 0;
+  virtual bool union_ (const vrange &);
+  virtual bool intersect (const vrange &);
   virtual bool singleton_p (tree *result = NULL) const;
   virtual bool contains_p (tree cst) const;
-  virtual bool zero_p () const = 0;
-  virtual bool nonzero_p () const = 0;
-  virtual void set_nonzero (tree type) = 0;
-  virtual void set_zero (tree type) = 0;
-  virtual void set_nonnegative (tree type) = 0;
-  virtual bool fits_p (const vrange &r) const = 0;
+  virtual bool zero_p () const;
+  virtual bool nonzero_p () const;
+  virtual void set_nonzero (tree type);
+  virtual void set_zero (tree type);
+  virtual void set_nonnegative (tree type);
+  virtual bool fits_p (const vrange &r) const;
 
   bool varying_p () const;
   bool undefined_p () const;
@@ -236,27 +236,13 @@ private:
 };
 
 // Unsupported temporaries may be created by ranger before it's known
-// they're unsupported, or by vr_values::get_value_range.  All
-// operations except construction cause a trap.
+// they're unsupported, or by vr_values::get_value_range.
 
 class unsupported_range : public vrange
 {
 public:
   unsupported_range ();
-  virtual void set (tree, tree, value_range_kind) override;
-  virtual tree type () const override;
-  virtual bool supports_type_p (tree type) const override;
-  virtual void set_varying (tree type) override;
-  virtual void set_undefined () override;
   virtual void dump (FILE *) const override;
-  virtual bool union_ (const vrange &) override;
-  virtual bool intersect (const vrange &) override;
-  virtual bool zero_p () const override;
-  virtual bool nonzero_p () const override;
-  virtual void set_nonzero (tree) override;
-  virtual void set_zero (tree) override;
-  virtual void set_nonnegative (tree) override;
-  virtual bool fits_p (const vrange &) const override;
 };
 
 // Traits to implement vrange is_a<> and as_a<>.
@@ -369,7 +355,7 @@ public:
   wide_int upper_bound () const; // For irange/prange compatability.
 private:
   void init (tree type);
-  static unsupported_range m_unsupported;
+  unsupported_range m_unsupported;
   vrange *m_vrange;
   int_range_max m_irange;
   DISABLE_COPY_AND_ASSIGN (Value_Range);
