[RFC] Experimental C++ support (#331)

This change adds experimental support for C++ via Clang's
OpenCL C++ mode.

In that mode Clang uses OpenCL's generic address space for
a number of things so I've just added it to
clspv::AddressSpace to align clspv's internal convention
with what Clang does a bit better.

This currently has to be used with -inline-entry-points to
maximise the chances that all traces of generic address
space will have been removed before passes that don't
support it. I have another change that plugs LLVM's address
space inference pass and enables quite a bit more code to be
compiled (and the use of the generic address space generally)
but it requires a couple of minor changes to LLVM.

Kernel function overloads are forbidden in the FrontendPlugin
with a custom diagnostic message. Kernel function names
are demangled before the descriptor map creation and the
absence of overload guarantees name unicity.

Signed-off-by: Kévin Petit <kpet@free.fr>
diff --git a/lib/Compiler.cpp b/lib/Compiler.cpp
index 2ce13cd..b386cb7 100644
--- a/lib/Compiler.cpp
+++ b/lib/Compiler.cpp
@@ -383,7 +383,12 @@
     instance.getDiagnosticOpts().VerifyPrefixes.push_back("expected");
   }
 
-  clang::LangStandard::Kind standard = clang::LangStandard::lang_opencl12;
+  clang::LangStandard::Kind standard;
+  if (clspv::Option::CPlusPlus()) {
+    standard = clang::LangStandard::lang_openclcpp;
+  } else {
+    standard = clang::LangStandard::lang_opencl12;
+  }
 
   // We are targeting OpenCL 1.2 only
   instance.getLangOpts().OpenCLVersion = 120;
@@ -602,6 +607,10 @@
     pm->add(clspv::createInlineFuncWithSingleCallSitePass());
   }
 
+  if (clspv::Option::CPlusPlus()) {
+    pm->add(clspv::createDemangleKernelNamesPass());
+  }
+
   if (0 == pmBuilder.OptLevel) {
     // Mem2Reg pass should be run early because O0 level optimization leaves
     // redundant alloca, load and store instructions from function arguments.
@@ -691,6 +700,12 @@
     return -1;
   }
 
+  if (clspv::Option::CPlusPlus() &&
+      !clspv::Option::InlineEntryPoints()) {
+    llvm::errs() << "cannot use -c++ without -inline-entry-points\n";
+    return -1;
+  }
+
   return 0;
 }
 } // namespace