From: Sven van Haastregt Date: Mon, 23 Apr 2018 11:23:47 +0000 (+0000) Subject: [OpenCL] Reject virtual functions for OpenCL C++ X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1fb3c210ec2babc6b741fc4b8607c20e015fba4e;p=clang [OpenCL] Reject virtual functions for OpenCL C++ Differential Revision: https://reviews.llvm.org/D45873 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@330579 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index cc4232fc4f..7c7c0fb24d 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -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, DefaultIgnore; diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index e7d8302e5c..7285506507 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -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") diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index f904e65e72..c516738fb7 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -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"); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index f17212d9b3..ef3d8c39b7 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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 index 0000000000..da08bfde95 --- /dev/null +++ b/test/Parser/opencl-cxx-virtual.cl @@ -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 +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; +}