summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp21
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp21
-rw-r--r--clang/lib/Sema/SemaType.cpp5
-rw-r--r--clang/test/SemaOpenCLCXX/newdelete.cl55
4 files changed, 98 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f5e48210924..e21f380fb71 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13007,6 +13007,13 @@ CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
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,
@@ -13022,6 +13029,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
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->getAs<PointerType>()) {
+ ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
+
// Check that the result type is what we expect.
if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
return SemaRef.Diag(FnDecl->getLocation(),
@@ -13047,6 +13061,13 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
<< 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()->getAs<PointerType>()) {
+ FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
+ }
+ }
if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
ExpectedFirstParamType)
return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 2847069ce56..5d1001dc84d 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2146,7 +2146,8 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
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 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
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 @@ void Sema::DeclareGlobalNewDelete() {
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 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType Pointee = Type->getAs<PointerType>()->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 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
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 ||
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index ac85e016ba0..1f6034a07d3 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -7173,8 +7173,9 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
// 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:
diff --git a/clang/test/SemaOpenCLCXX/newdelete.cl b/clang/test/SemaOpenCLCXX/newdelete.cl
new file mode 100644
index 00000000000..ce6273f3be7
--- /dev/null
+++ b/clang/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;
+}
OpenPOWER on IntegriCloud