Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -12983,6 +12983,13 @@ return false; } +static QualType +RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) { + QualType QTy = PtrTy->getPointeeType(); + QTy = SemaRef.Context.removeAddrSpaceQualType(QTy); + return SemaRef.Context.getPointerType(QTy); +} + static inline bool CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, CanQualType ExpectedResultType, @@ -12998,6 +13005,13 @@ diag::err_operator_new_delete_dependent_result_type) << FnDecl->getDeclName() << ExpectedResultType; + // OpenCL C++: the operator is valid on any address space. + if (SemaRef.getLangOpts().OpenCLCPlusPlus) { + if (auto *PtrTy = ResultType.getTypePtr()->getAs()) { + ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); + } + } + // Check that the result type is what we expect. if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) return SemaRef.Diag(FnDecl->getLocation(), @@ -13023,6 +13037,13 @@ << FnDecl->getDeclName() << ExpectedFirstParamType; // Check that the first parameter type is what we expect. + if (SemaRef.getLangOpts().OpenCLCPlusPlus) { + // OpenCL C++: the operator is valid on any address space. + if (auto *PtrTy = FnDecl->getParamDecl(0)->getType().getTypePtr() + ->getAs()) { + FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); + } + } if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != ExpectedFirstParamType) return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -2146,7 +2146,8 @@ else if (AllocType->isVariablyModifiedType()) return Diag(Loc, diag::err_variably_modified_new_type) << AllocType; - else if (AllocType.getAddressSpace() != LangAS::Default) + else if (AllocType.getAddressSpace() != LangAS::Default && + !getLangOpts().OpenCLCPlusPlus) return Diag(Loc, diag::err_address_space_qualified_new) << AllocType.getUnqualifiedType() << AllocType.getQualifiers().getAddressSpaceAttributePrintValue(); @@ -2362,6 +2363,11 @@ LookupQualifiedName(R, Context.getTranslationUnitDecl()); } + if (getLangOpts().OpenCLCPlusPlus && R.empty()) { + Diag(StartLoc, diag::err_openclcxx_not_supported) << "default new"; + return true; + } + assert(!R.empty() && "implicitly declared allocation functions not found"); assert(!R.isAmbiguous() && "global allocation functions are ambiguous"); @@ -2597,6 +2603,11 @@ if (GlobalNewDeleteDeclared) return; + // OpenCL C++ 1.0 s2.9: the implicitly declared new and delete operators + // are not supported. + if (getLangOpts().OpenCLCPlusPlus) + return; + // C++ [basic.std.dynamic]p2: // [...] The following allocation and deallocation functions (18.4) are // implicitly declared in global scope in each translation unit of a @@ -3230,7 +3241,8 @@ QualType Pointee = Type->getAs()->getPointeeType(); QualType PointeeElem = Context.getBaseElementType(Pointee); - if (Pointee.getAddressSpace() != LangAS::Default) + if (Pointee.getAddressSpace() != LangAS::Default && + !getLangOpts().OpenCLCPlusPlus) return Diag(Ex.get()->getLocStart(), diag::err_address_space_qualified_delete) << Pointee.getUnqualifiedType() @@ -3305,6 +3317,11 @@ } if (!OperatorDelete) { + if (getLangOpts().OpenCLCPlusPlus) { + Diag(StartLoc, diag::err_openclcxx_not_supported) << "default delete"; + return ExprError(); + } + bool IsComplete = isCompleteType(StartLoc, Pointee); bool CanProvideSize = IsComplete && (!ArrayForm || UsualArrayDeleteWantsSize || Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -7137,8 +7137,9 @@ // The default address space name for arguments to a function in a // program, or local variables of a function is __private. All function // arguments shall be in the __private address space. - if (State.getSema().getLangOpts().OpenCLVersion <= 120) { - ImpAddr = LangAS::opencl_private; + if (State.getSema().getLangOpts().OpenCLVersion <= 120 && + !State.getSema().getLangOpts().OpenCLCPlusPlus) { + ImpAddr = LangAS::opencl_private; } else { // If address space is not set, OpenCL 2.0 defines non private default // address spaces for some cases: Index: test/SemaOpenCLCXX/newdelete.cl =================================================================== --- /dev/null +++ test/SemaOpenCLCXX/newdelete.cl @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only + +class A { + public: + A() : x(21) {} + int x; +}; + +typedef __SIZE_TYPE__ size_t; + +class B { + public: + B() : bx(42) {} + void *operator new(size_t); + void operator delete(void *ptr); + int bx; +}; + +// There are no global user-defined new operators at this point. Test that clang +// rejects these gracefully. +void test_default_new_delete(void *buffer, A **pa) { + A *a = new A; // expected-error {{'default new' is not supported in OpenCL C++}} + delete a; // expected-error {{'default delete' is not supported in OpenCL C++}} + *pa = new (buffer) A; // expected-error {{'default new' is not supported in OpenCL C++}} +} + +// expected-note@+1 {{candidate function not viable: requires 2 arguments, but 1 was provided}} +void *operator new(size_t _s, void *ptr) noexcept { + return ptr; +} + +// expected-note@+1 {{candidate function not viable: requires 2 arguments, but 1 was provided}} +void *operator new[](size_t _s, void *ptr) noexcept { + return ptr; +} + +void test_new_delete(void *buffer, A **a, B **b) { + *a = new A; // expected-error {{no matching function for call to 'operator new'}} + delete a; // expected-error {{'default delete' is not supported in OpenCL C++}} + + *a = new A[20]; // expected-error {{no matching function for call to 'operator new[]'}} + delete[] *a; // expected-error {{'default delete' is not supported in OpenCL C++}} + + // User-defined placement new is supported. + *a = new (buffer) A; + + // User-defined placement new[] is supported. + *a = new (buffer) A[30]; + + // User-defined new is supported. + *b = new B; + + // User-defined delete is supported. + delete *b; +}