mirror of https://github.com/microsoft/clang.git
[OpenCL] Support new/delete in Sema
Reject uses of the default new/delete operators with a diagnostic instead of a crash in OpenCL C++ mode and accept user-defined forms. Differential Revision: https://reviews.llvm.org/D46651 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@334700 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9c72f2596e
commit
af56077940
|
@ -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)
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue