diff options
| author | Sven van Haastregt <sven.vanhaastregt@arm.com> | 2018-06-14 09:51:54 +0000 | 
|---|---|---|
| committer | Sven van Haastregt <sven.vanhaastregt@arm.com> | 2018-06-14 09:51:54 +0000 | 
| commit | e6e76fd8390058d4d44ab4ae09347e80e3ea8d4d (patch) | |
| tree | 9065796af4f73e01fccc5f7f719444686aa223cf | |
| parent | c0d53aba7b596df773a58a1d22dee8a670699708 (diff) | |
| download | bcm5719-llvm-e6e76fd8390058d4d44ab4ae09347e80e3ea8d4d.tar.gz bcm5719-llvm-e6e76fd8390058d4d44ab4ae09347e80e3ea8d4d.zip  | |
[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
llvm-svn: 334700
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 21 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 21 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 5 | ||||
| -rw-r--r-- | clang/test/SemaOpenCLCXX/newdelete.cl | 55 | 
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; +}  | 

