Avoid a C++ runtime dependency.

Short-term, we will need to use these macros and build without RTTI when
defining any virtual base class. Long-term, it would be good to remove
these constraints, but it will require some downstream work.

Bug: 132
Change-Id: I3bc65bb12d7653978612b7d1bf06f772a2f3b1cd
Reviewed-on: https://boringssl-review.googlesource.com/18344
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h
index fb02d35..5a2e560 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -144,6 +144,8 @@
 
 #include <openssl/base.h>
 
+#include <stdlib.h>
+
 #include <type_traits>
 #include <utility>
 
@@ -217,6 +219,17 @@
   return UniquePtr<T>(New<T>(std::forward<Args>(args)...));
 }
 
+/* HAS_VIRTUAL_DESTRUCTOR should be declared in any base class which defines a
+ * virtual destructor. This avoids a dependency on |_ZdlPv| and prevents the
+ * class from being used with |delete|. */
+#define HAS_VIRTUAL_DESTRUCTOR \
+  void operator delete(void *) { abort(); }
+
+/* PURE_VIRTUAL should be used instead of = 0 when defining pure-virtual
+ * functions. This avoids a dependency on |__cxa_pure_virtual| but loses
+ * compile-time checking. */
+#define PURE_VIRTUAL { abort(); }
+
 
 /* Protocol versions.
  *
@@ -753,17 +766,18 @@
 class SSLKeyShare {
  public:
   virtual ~SSLKeyShare() {}
+  HAS_VIRTUAL_DESTRUCTOR
 
   /* Create returns a SSLKeyShare instance for use with group |group_id| or
    * nullptr on error. */
   static UniquePtr<SSLKeyShare> Create(uint16_t group_id);
 
   /* GroupID returns the group ID. */
-  virtual uint16_t GroupID() const = 0;
+  virtual uint16_t GroupID() const PURE_VIRTUAL;
 
   /* Offer generates a keypair and writes the public value to
    * |out_public_key|. It returns true on success and false on error. */
-  virtual bool Offer(CBB *out_public_key) = 0;
+  virtual bool Offer(CBB *out_public_key) PURE_VIRTUAL;
 
   /* Accept performs a key exchange against the |peer_key| generated by |offer|.
    * On success, it returns true, writes the public value to |out_public_key|,
@@ -790,7 +804,7 @@
    * TODO(davidben): out_secret should be a smart pointer. */
   virtual bool Finish(uint8_t **out_secret, size_t *out_secret_len,
                       uint8_t *out_alert, const uint8_t *peer_key,
-                      size_t peer_key_len) = 0;
+                      size_t peer_key_len) PURE_VIRTUAL;
 };
 
 /* ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it