Build: Improve C++ support

Can choose the C++ standard (C++98/11/14/17/2a)
Can link with standard C++ library (libstdc++)
Add support of C++ exceptions
Add support of C++ RTTI
Add C++ options to subsys/cpp/Kconfig
Implements new and delete using k_malloc and k_free
if CONFIG_HEAP_MEM_POOL_SIZE is defined

Signed-off-by: Benoit Leforestier <benoit.leforestier@gmail.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e78978..ccff722 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -105,6 +105,28 @@
   assert(0 "Unreachable code. Expected optimization level to have been chosen. See misc/Kconfig.")
 endif()
 
+# Dialects of C++, corresponding to the multiple published ISO standards.
+# Which standard it implements can be selected using the -std= command-line option.
+set_ifndef(DIALECT_STD_CPP98 "c++98")
+set_ifndef(DIALECT_STD_CPP11 "c++11")
+set_ifndef(DIALECT_STD_CPP14 "c++14")
+set_ifndef(DIALECT_STD_CPP17 "c++17")
+set_ifndef(DIALECT_STD_CPP2A "c++2a")
+
+if(CONFIG_STD_CPP98)
+  set(STD_CPP_DIALECT ${DIALECT_STD_CPP98})
+elseif(CONFIG_STD_CPP11)
+  set(STD_CPP_DIALECT ${DIALECT_STD_CPP11}) # Default
+elseif(CONFIG_STD_CPP14)
+  set(STD_CPP_DIALECT ${DIALECT_STD_CPP14})
+elseif(CONFIG_STD_CPP17)
+  set(STD_CPP_DIALECT ${DIALECT_STD_CPP17})
+elseif(CONFIG_STD_CPP2A)
+  set(STD_CPP_DIALECT ${DIALECT_STD_CPP2A})
+else()
+  assert(0 "Unreachable code. Expected C++ standard to have been chosen. See misc/Kconfig.")
+endif()
+
 zephyr_compile_options(
   ${OPTIMIZATION_FLAG} # Usually -Os
   -g # TODO: build configuration enough?
@@ -120,17 +142,27 @@
 )
 
 zephyr_compile_options(
-  $<$<COMPILE_LANGUAGE:CXX>:-std=c++11>
+  $<$<COMPILE_LANGUAGE:CXX>:-std=${STD_CPP_DIALECT}>
   $<$<COMPILE_LANGUAGE:CXX>:-fcheck-new>
   $<$<COMPILE_LANGUAGE:CXX>:-ffunction-sections>
   $<$<COMPILE_LANGUAGE:CXX>:-fdata-sections>
-  $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
-  $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
 
   $<$<COMPILE_LANGUAGE:ASM>:-xassembler-with-cpp>
   $<$<COMPILE_LANGUAGE:ASM>:-D_ASMLANGUAGE>
 )
 
+if(NOT CONFIG_RTTI)
+zephyr_compile_options(
+  $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
+)
+endif()
+
+if(NOT CONFIG_EXCEPTIONS)
+zephyr_compile_options(
+  $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
+)
+endif()
+
 if(NOT CONFIG_NATIVE_APPLICATION)
 zephyr_ld_options(
   -nostartfiles
@@ -141,6 +173,12 @@
 )
 endif()
 
+if(CONFIG_LIB_CPLUSPLUS)
+zephyr_ld_options(
+  -lstdc++
+)
+endif()
+
 # ==========================================================================
 #
 # cmake -DW=... settings
diff --git a/include/kernel.h b/include/kernel.h
index 4d1825c..30e449f 100644
--- a/include/kernel.h
+++ b/include/kernel.h
@@ -4846,61 +4846,6 @@
 }
 #endif
 
-#if defined(CONFIG_CPLUSPLUS) && defined(__cplusplus)
-/*
- * Define new and delete operators.
- * At this moment, the operators do nothing since objects are supposed
- * to be statically allocated.
- */
-inline void operator delete(void *ptr)
-{
-	(void)ptr;
-}
-
-inline void operator delete[](void *ptr)
-{
-	(void)ptr;
-}
-
-inline void *operator new(size_t size)
-{
-	(void)size;
-	return NULL;
-}
-
-inline void *operator new[](size_t size)
-{
-	(void)size;
-	return NULL;
-}
-
-/* Placement versions of operator new and delete */
-inline void operator delete(void *ptr1, void *ptr2)
-{
-	(void)ptr1;
-	(void)ptr2;
-}
-
-inline void operator delete[](void *ptr1, void *ptr2)
-{
-	(void)ptr1;
-	(void)ptr2;
-}
-
-inline void *operator new(size_t size, void *ptr)
-{
-	(void)size;
-	return ptr;
-}
-
-inline void *operator new[](size_t size, void *ptr)
-{
-	(void)size;
-	return ptr;
-}
-
-#endif /* defined(CONFIG_CPLUSPLUS) && defined(__cplusplus) */
-
 #include <tracing.h>
 #include <syscalls/kernel.h>
 
diff --git a/misc/Kconfig b/misc/Kconfig
index c53f730..105fea9 100644
--- a/misc/Kconfig
+++ b/misc/Kconfig
@@ -111,6 +111,7 @@
 	help
 	  Run a linker address generation validity checker at the end of the
 	  build.
+
 endmenu
 
 menu "Compiler Options"
@@ -175,11 +176,6 @@
 	  and can be used to change compiler optimization, warning and error
 	  messages, and so on.
 
-config CPLUSPLUS
-	bool "Enable C++ support for the application"
-	help
-	  This option enables the use of applications built with C++.
-
 endmenu
 
 menu "Build Options"
diff --git a/subsys/Kconfig b/subsys/Kconfig
index 76feac7..d51b582 100644
--- a/subsys/Kconfig
+++ b/subsys/Kconfig
@@ -9,6 +9,8 @@
 
 source "subsys/console/Kconfig"
 
+source "subsys/cpp/Kconfig"
+
 source "subsys/debug/Kconfig"
 
 source "subsys/disk/Kconfig"
diff --git a/subsys/cpp/CMakeLists.txt b/subsys/cpp/CMakeLists.txt
index 5daacc8..84046f3 100644
--- a/subsys/cpp/CMakeLists.txt
+++ b/subsys/cpp/CMakeLists.txt
@@ -4,4 +4,5 @@
   cpp_init_array.c
   cpp_ctors.c
   cpp_dtors.c
+  cpp_new.cpp
 )
diff --git a/subsys/cpp/Kconfig b/subsys/cpp/Kconfig
new file mode 100644
index 0000000..ee13e73
--- /dev/null
+++ b/subsys/cpp/Kconfig
@@ -0,0 +1,70 @@
+# Kconfig - C++ configuration options
+
+#
+# Copyright (c) 2018 B. Leforestier
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+menu "C++ Options"
+
+config CPLUSPLUS
+	bool "Enable C++ support for the application"
+	help
+	  This option enables the use of applications built with C++.
+
+choice
+	prompt "C++ Standard"
+	default STD_CPP11
+	help
+	  C++ Standards.
+
+config STD_CPP98
+	bool "C++ 98"
+	help
+	  1998 C++ standard as modified by the 2003 technical corrigendum
+	  and some later defect reports.
+
+config STD_CPP11
+	bool "C++ 11"
+	help
+	  2011 C++ standard, previously known as C++0x.
+
+config STD_CPP14
+	bool "C++ 14"
+	help
+	  2014 C++ standard.
+
+config STD_CPP17
+	bool "C++ 17"
+	help
+	  2017 C++ standard, previously known as C++0x.
+
+config STD_CPP2A
+	bool "C++ 2a"
+	help
+	  Next revision of the C++ standard, which is expected to be published in 2020.
+
+endchoice
+
+config LIB_CPLUSPLUS
+	depends on CPLUSPLUS
+	bool "Link with STD C++ library"
+	help
+	  Link with STD C++ Library.
+
+config EXCEPTIONS
+	depends on CPLUSPLUS
+	select LIB_CPLUSPLUS
+	bool "Enable C++ exceptions support"
+	help
+	  This option enables support of C++ exceptions.
+
+config RTTI
+	depends on CPLUSPLUS
+	select LIB_CPLUSPLUS
+	bool "Enable C++ RTTI support"
+	help
+	  This option enables support of C++ RTTI.
+
+endmenu
diff --git a/subsys/cpp/cpp_new.cpp b/subsys/cpp/cpp_new.cpp
new file mode 100644
index 0000000..29f6b64
--- /dev/null
+++ b/subsys/cpp/cpp_new.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_LIB_CPLUSPLUS)
+#include <new>
+#endif // CONFIG_LIB_CPLUSPLUS
+#include <kernel.h>
+
+void* operator new(size_t size)
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	void* ptr = k_malloc(size);
+#if defined(__cpp_exceptions) && defined(CONFIG_LIB_CPLUSPLUS)
+	if (!ptr)
+		throw std::bad_alloc();
+#endif
+	return ptr;
+#else
+	ARG_UNUSED(size);
+	return NULL;
+#endif
+}
+
+void* operator new[](size_t size)
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	void* ptr = k_malloc(size);
+#if defined(__cpp_exceptions) && defined(CONFIG_LIB_CPLUSPLUS)
+	if (!ptr)
+		throw std::bad_alloc();
+#endif
+	return ptr;
+#else
+	ARG_UNUSED(size);
+	return NULL;
+#endif
+}
+
+void operator delete(void* ptr) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	k_free(ptr);
+#else
+	ARG_UNUSED(ptr);
+#endif
+}
+
+void operator delete[](void* ptr) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	k_free(ptr);
+#else
+	ARG_UNUSED(ptr);
+#endif
+}
+
+#if defined(CONFIG_LIB_CPLUSPLUS)
+void* operator new(size_t size, const std::nothrow_t&) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	return k_malloc(size);
+#else
+	ARG_UNUSED(size);
+	return NULL;
+#endif
+}
+
+void* operator new[](size_t size, const std::nothrow_t&) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	return k_malloc(size);
+#else
+	ARG_UNUSED(size);
+	return NULL;
+#endif
+}
+
+void operator delete(void* ptr, const std::nothrow_t&) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	k_free(ptr);
+#else
+	ARG_UNUSED(ptr);
+#endif
+}
+
+void operator delete[](void* ptr, const std::nothrow_t&) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	k_free(ptr);
+#else
+	ARG_UNUSED(ptr);
+#endif
+}
+#endif // CONFIG_LIB_CPLUSPLUS
+
+#if (__cplusplus > 201103L)
+void operator delete(void* ptr, size_t) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	k_free(ptr);
+#else
+	ARG_UNUSED(ptr);
+#endif
+}
+
+void operator delete[](void* ptr, size_t) noexcept
+{
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	k_free(ptr);
+#else
+	ARG_UNUSED(ptr);
+#endif
+}
+#endif // __cplusplus > 201103L