diff options
author | Anastasia Stulova <anastasia.stulova@arm.com> | 2016-03-03 13:33:19 +0000 |
---|---|---|
committer | Anastasia Stulova <anastasia.stulova@arm.com> | 2016-03-03 13:33:19 +0000 |
commit | 1f95cc097c2b5290ab050cdf64f2ac0dd78ef015 (patch) | |
tree | 0fe8b5da9bb56623d846c51e7d8e461178820de4 /clang/lib/Sema | |
parent | f4336ac9eb889739644724ff5f6152d5ac663fad (diff) | |
download | bcm5719-llvm-1f95cc097c2b5290ab050cdf64f2ac0dd78ef015.tar.gz bcm5719-llvm-1f95cc097c2b5290ab050cdf64f2ac0dd78ef015.zip |
[OpenCL] Apply missing restrictions for Blocks in OpenCL v2.0
Applying the following restrictions for block types in OpenCL (v2.0 s6.12.5):
- __block storage class is disallowed
- every block declaration must be const qualified and initialized
- a block can't be used as a return type of a function
- a blocks can't be used to declare a structure or union field
- extern speficier is disallowed
Corrected image and sampler types diagnostics with struct and unions.
Review: http://reviews.llvm.org/D16928
llvm-svn: 262616
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 78 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 11 |
2 files changed, 65 insertions, 24 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f20b4d06287..74d6f918972 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6585,7 +6585,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } - // OpenCL v1.2 s6.8 -- The static qualifier is valid only in program + // OpenCL v1.2 s6.8 - The static qualifier is valid only in program // scope. if (getLangOpts().OpenCLVersion == 120 && !getOpenCLOptions().cl_clang_storage_class_specifiers && @@ -6595,12 +6595,44 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } - // OpenCL v1.2 s6.5 - All program scope variables must be declared in the - // __constant address space. - // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static - // variables inside a function can also be declared in the global - // address space. if (getLangOpts().OpenCL) { + // OpenCL v2.0 s6.12.5 - The __block storage type is not supported. + if (NewVD->hasAttr<BlocksAttr>()) { + Diag(NewVD->getLocation(), diag::err_opencl_block_storage_type); + return; + } + + if (T->isBlockPointerType()) { + // OpenCL v2.0 s6.12.5 - Any block declaration must be const qualified and + // can't use 'extern' storage class. + if (!T.isConstQualified()) { + Diag(NewVD->getLocation(), diag::err_opencl_invalid_block_declaration) + << 0 /*const*/; + NewVD->setInvalidDecl(); + return; + } + if (NewVD->hasExternalStorage()) { + Diag(NewVD->getLocation(), diag::err_opencl_extern_block_declaration); + NewVD->setInvalidDecl(); + return; + } + // OpenCL v2.0 s6.12.5 - Blocks with variadic arguments are not supported. + // TODO: this check is not enough as it doesn't diagnose the typedef + const BlockPointerType *BlkTy = T->getAs<BlockPointerType>(); + const FunctionProtoType *FTy = + BlkTy->getPointeeType()->getAs<FunctionProtoType>(); + if (FTy && FTy->isVariadic()) { + Diag(NewVD->getLocation(), diag::err_opencl_block_proto_variadic) + << T << NewVD->getSourceRange(); + NewVD->setInvalidDecl(); + return; + } + } + // OpenCL v1.2 s6.5 - All program scope variables must be declared in the + // __constant address space. + // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static + // variables inside a function can also be declared in the global + // address space. if (NewVD->isFileVarDecl()) { if (!T->isSamplerT() && !(T.getAddressSpace() == LangAS::opencl_constant || @@ -6735,19 +6767,6 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { NewVD->setInvalidDecl(); return; } - - // OpenCL v2.0 s6.12.5 - Blocks with variadic arguments are not supported. - if (LangOpts.OpenCL && T->isBlockPointerType()) { - const BlockPointerType *BlkTy = T->getAs<BlockPointerType>(); - const FunctionProtoType *FTy = - BlkTy->getPointeeType()->getAs<FunctionProtoType>(); - if (FTy->isVariadic()) { - Diag(NewVD->getLocation(), diag::err_opencl_block_proto_variadic) - << T << NewVD->getSourceRange(); - NewVD->setInvalidDecl(); - return; - } - } } /// \brief Perform semantic checking on a newly-created variable @@ -10058,6 +10077,18 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; + if (getLangOpts().OpenCL) { + // OpenCL v2.0 s6.12.5 - Every block variable declaration must have an + // initialiser + if (var->getTypeSourceInfo()->getType()->isBlockPointerType() && + !var->hasInit()) { + Diag(var->getLocation(), diag::err_opencl_invalid_block_declaration) + << 1 /*Init*/; + var->setInvalidDecl(); + return; + } + } + // In Objective-C, don't allow jumps past the implicit initialization of a // local retaining variable. if (getLangOpts().ObjC1 && @@ -13110,10 +13141,11 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, D.setInvalidType(); } - // OpenCL 1.2 spec, s6.9 r: - // The event type cannot be used to declare a structure or union field. - if (LangOpts.OpenCL && T->isEventT()) { - Diag(Loc, diag::err_event_t_struct_field); + // OpenCL v1.2 s6.9b,r & OpenCL v2.0 s6.12.5 - The following types cannot be + // used as structure or union field: image, sampler, event or block types. + if (LangOpts.OpenCL && (T->isEventT() || T->isImageType() || + T->isSamplerT() || T->isBlockPointerType())) { + Diag(Loc, diag::err_opencl_type_struct_or_union_field) << T; D.setInvalidType(); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 135b78a4509..73c5bcc0067 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3921,7 +3921,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (T->isHalfType()) { if (S.getLangOpts().OpenCL) { if (!S.getOpenCLOptions().cl_khr_fp16) { - S.Diag(D.getIdentifierLoc(), diag::err_opencl_half_return) << T; + S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return) + << T << 0 /*pointer hint*/; D.setInvalidType(true); } } else if (!S.getLangOpts().HalfArgsAndReturns) { @@ -3931,6 +3932,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } + // OpenCL v2.0 s6.12.5 - A block cannot be the return value of a + // function. + if (LangOpts.OpenCL && T->isBlockPointerType()) { + S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return) + << T << 1 /*hint off*/; + D.setInvalidType(true); + } + // Methods cannot return interface types. All ObjC objects are // passed by reference. if (T->isObjCObjectType()) { |