diff -ruN grub2.orig/hello/hello.c grub2/hello/hello.c --- grub2.orig/hello/hello.c 2007-07-22 01:32:21.000000000 +0200 +++ grub2/hello/hello.c 2008-06-25 19:51:30.907250000 +0200 @@ -18,25 +18,164 @@ * along with GRUB. If not, see . */ + +// Include C++ support first +#include +#include + +extern "C" { // TODO: add extern "C" to all includes [__cplusplus] #include #include #include #include #include #include +} + + +// Class to set and restore grub_mm_debug in a block + +class do_mm_debug +{ +#ifdef MM_DEBUG +public: + explicit do_mm_debug (bool debug = true) + : m_debug_old (grub_mm_debug) + { grub_mm_debug = (int)debug; } + + ~do_mm_debug () + { grub_mm_debug = m_debug_old; } + +private: + int m_debug_old; +#else + +public: + do_mm_debug () { } + explicit do_mm_debug (bool) { } +#endif +}; + + + +// Classes to test single inheritance and vtable + +class A +{ +public: + explicit A (const char * name); + virtual ~A (); + + virtual void hello () const; + +protected: + char * m_name; +}; + +class B : public A +{ +public: + explicit B (const char * name); + virtual ~B (); + + virtual void hello () const; +}; + + + +A::A (const char * name) +: m_name (new char[grub_strlen (name) + 1]) // calls grub_fatal on failure +{ + grub_strcpy (m_name, name); + grub_printf ("%sA::A ()\n", m_name); +} + +A::~A () +{ + grub_printf ("%sA::~A ()\n", m_name); + delete [] m_name; +} + +void A::hello () const +{ + grub_printf ("%sA::hello (): Something wrong!\n", m_name); +} + + +B::B (const char * name) +: A (name) +{ + grub_printf ("%sB::B ()\n", m_name); +} + +B::~B () +{ + grub_printf ("%sB::~B ()\n", m_name); +} + +void B::hello () const +{ + grub_printf ("%sB::hello (): Hello C++ World\n", m_name); +} + + +// Globals + +//static B gb ("gb."); // NOT SUPPORTED + +static char gb_mem[sizeof (B)]; +B & gb = *(B *)gb_mem; // ctor called by placement new + +A * pa = 0; + + +static void +say_hello (const A & a) +{ + a.hello (); +} + static grub_err_t grub_cmd_hello (struct grub_arg_list *state __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_printf ("Hello World\n"); - return 0; + do_mm_debug here; + + // call virtual function B::hello () for all objects + + say_hello (gb); // global object + + if (pa) + { + say_hello (*pa); // global pointer (actually B *) + delete pa; + pa = 0; + } + + //static B sb ("sb."); // NOT SUPPORTED + //say_hello (&sb); + + B vb ("vb."); + say_hello (vb); // local object + + say_hello ( B("_temp_B.") ); // temporary object + + return GRUB_ERR_NONE; } GRUB_MOD_INIT(hello) { - (void)mod; /* To stop warning. */ + { + do_mm_debug here; + + pa = new (std::nothrow) B ("pa->"); + if (! pa) + return; + + new (gb_mem) B ("gb."); // returns &gb + } grub_register_command ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH, "hello", "Say hello", 0); } @@ -44,4 +183,11 @@ GRUB_MOD_FINI(hello) { grub_unregister_command ("hello"); + + do_mm_debug here; + + gb.~B(); + + delete pa; + pa = 0; } diff -ruN grub2.orig/include/grub/dl.hpp grub2/include/grub/dl.hpp --- grub2.orig/include/grub/dl.hpp 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/dl.hpp 2008-06-25 11:23:48.000000000 +0200 @@ -0,0 +1,37 @@ +// GRUB2 C++ GRUB_MOD_INIT/FINI + +#ifndef GRUB_DL_HPP +#define GRUB_DL_HPP 1 + +extern "C" { + #include // GRUB_MOD_INIT/FINI +} + + +// TODO: Add this to dl.h [__cplusplus] + +#undef GRUB_MOD_INIT +#undef GRUB_MOD_FINI + +#define GRUB_MOD_INIT(name) \ +extern "C" { \ + static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \ + void grub_##name##_init (void); \ +} \ +void \ +grub_##name##_init (void) { grub_mod_init (0); } \ +static void \ +grub_mod_init (grub_dl_t mod __attribute__ ((unused))) + +#define GRUB_MOD_FINI(name) \ +extern "C" { \ + static void grub_mod_fini (void) __attribute__ ((used)); \ + void grub_##name##_fini (void); \ +} \ +void \ +grub_##name##_fini (void) { grub_mod_fini (); } \ +static void \ +grub_mod_fini (void) + +#endif + diff -ruN grub2.orig/include/grub/mm.hpp grub2/include/grub/mm.hpp --- grub2.orig/include/grub/mm.hpp 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/mm.hpp 2008-06-25 13:34:00.000000000 +0200 @@ -0,0 +1,102 @@ +// GRUB2 C++ memory management + +#ifndef GRUB_MM_HPP +#define GRUB_MM_HPP 1 + +extern "C" { + #include +} + + +// TODO: Add grub_malloc_nonull () to mm.c ??? + +static void * +grub_malloc_nonull (grub_size_t size) +{ + void * p = grub_malloc (size); + if (! p) + grub_fatal ("out of memory"); // no-exceptions, sorry + return p; +} + + +// TODO: add new/delete to [__cplusplus] + +// Standard (throw) new + +inline void * +operator new (grub_size_t size) +{ + return grub_malloc_nonull (size); +} + +inline void * +operator new[] (grub_size_t size) +{ + return grub_malloc_nonull (size); +} + + +// Standard nothrow new + +namespace std { + enum nothrow_t { nothrow }; +} + +inline void * +operator new (grub_size_t size, std::nothrow_t /*mode*/) throw () +{ + return grub_malloc (size); +} + +inline void * +operator new[] (grub_size_t size, std::nothrow_t /*mode*/) throw () +{ + return grub_malloc (size); +} + + +// Standard delete + +inline void +operator delete (void * ptr) throw () +{ + grub_free (ptr); +} + +inline void +operator delete[] (void * ptr) throw () +{ + grub_free (ptr); +} + + +// Placement new + +inline void * +operator new (grub_size_t /*size*/, void * here) throw () +{ + return here; +} + +inline void * +operator new[] (grub_size_t /*size*/, void * here) throw () +{ + return here; +} + + +// Placement delete (not used if no-exceptions) + +inline void +operator delete (void * /*ptr*/, void * /*here*/) throw () +{ +} + +inline void +operator delete[] (void * /*ptr*/, void * /*here*/) throw () +{ +} + +#endif +