]> granicus.if.org Git - clang/commitdiff
[OpenCL] Reject virtual functions for OpenCL C++
authorSven van Haastregt <sven.vanhaastregt@arm.com>
Mon, 23 Apr 2018 11:23:47 +0000 (11:23 +0000)
committerSven van Haastregt <sven.vanhaastregt@arm.com>
Mon, 23 Apr 2018 11:23:47 +0000 (11:23 +0000)
Differential Revision: https://reviews.llvm.org/D45873

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@330579 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/LangOptions.def
lib/Frontend/CompilerInvocation.cpp
lib/Parse/ParseDecl.cpp
test/Parser/opencl-cxx-virtual.cl [new file with mode: 0644]

index cc4232fc4f18c97b597f0766ac68b70e1527143d..7c7c0fb24da7189e7ec18cbd6239d16814600382 100644 (file)
@@ -1073,6 +1073,10 @@ def err_opencl_taking_function_address_parser : Error<
 def err_opencl_logical_exclusive_or : Error<
   "^^ is a reserved operator in OpenCL">;
 
+// OpenCL C++.
+def err_openclcxx_virtual_function : Error<
+  "virtual functions are not supported in OpenCL C++">;
+
 // OpenMP support.
 def warn_pragma_omp_ignored : Warning<
   "unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
index e7d8302e5c55921dadcb8b7bfa82ba016329ef7a..72855065078ca5b9521697a87a4d5f6e043eb5d3 100644 (file)
@@ -189,6 +189,7 @@ LANGOPT(ShortEnums        , 1, 0, "short enum types")
 
 LANGOPT(OpenCL            , 1, 0, "OpenCL")
 LANGOPT(OpenCLVersion     , 32, 0, "OpenCL C version")
+LANGOPT(OpenCLCPlusPlus   , 1, 0, "OpenCL C++")
 LANGOPT(OpenCLCPlusPlusVersion     , 32, 0, "OpenCL C++ version")
 LANGOPT(NativeHalfType    , 1, 0, "Native half type support")
 LANGOPT(NativeHalfArgsAndReturns, 1, 0, "Native half args and returns")
index f904e65e7243d34fe6cd740c9e847091fe5ffbc0..c516738fb7a51c49c3714430e71dc8ed6062ac86 100644 (file)
@@ -1927,6 +1927,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
     Opts.setDefaultFPContractMode(LangOptions::FPC_On);
     Opts.NativeHalfType = 1;
     Opts.NativeHalfArgsAndReturns = 1;
+    Opts.OpenCLCPlusPlus = Opts.CPlusPlus;
     // Include default header file for OpenCL.
     if (Opts.IncludeDefaultHeader) {
       PPOpts.Includes.push_back("opencl-c.h");
index f17212d9b3ae9a6eb89a11715db7389e80960b61..ef3d8c39b7d2677f6c96c151308b51ef2d9b5ae0 100644 (file)
@@ -3466,7 +3466,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
       isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID);
       break;
     case tok::kw_virtual:
-      isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
+      // OpenCL C++ v1.0 s2.9: the virtual function qualifier is not supported.
+      if (getLangOpts().OpenCLCPlusPlus) {
+        DiagID = diag::err_openclcxx_virtual_function;
+        PrevSpec = Tok.getIdentifierInfo()->getNameStart();
+        isInvalid = true;
+      }
+      else {
+        isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);
+      }
       break;
     case tok::kw_explicit:
       isInvalid = DS.setFunctionSpecExplicit(Loc, PrevSpec, DiagID);
diff --git a/test/Parser/opencl-cxx-virtual.cl b/test/Parser/opencl-cxx-virtual.cl
new file mode 100644 (file)
index 0000000..da08bfd
--- /dev/null
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -fsyntax-only -verify
+
+// Test that virtual functions and abstract classes are rejected.
+class virtual_functions {
+  virtual void bad1() {}
+  //expected-error@-1 {{virtual functions are not supported in OpenCL C++}}
+
+  virtual void bad2() = 0;
+  //expected-error@-1 {{virtual functions are not supported in OpenCL C++}}
+  //expected-error@-2 {{'bad2' is not virtual and cannot be declared pure}}
+};
+
+template <typename T>
+class X {
+  virtual T f();
+  //expected-error@-1 {{virtual functions are not supported in OpenCL C++}}
+};
+
+// Test that virtual base classes are allowed.
+struct A {
+  int a;
+  void foo();
+};
+
+struct B : virtual A {
+  int b;
+};
+
+struct C : public virtual A {
+  int c;
+};
+
+struct D : B, C {
+  int d;
+};
+
+kernel void virtual_inheritance() {
+  D d;
+
+  d.foo();
+  d.a = 11;
+  d.b = 22;
+  d.c = 33;
+  d.d = 44;
+}