Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -596,6 +596,7 @@ /// parser diagnostics def ext_no_declarators : ExtWarn<"declaration does not declare anything">, InGroup; +def err_no_declarators : Error<"declaration does not declare anything">; def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">, InGroup; def err_typedef_not_identifier : Error<"typedef name must be an identifier">; @@ -7692,6 +7693,22 @@ " in the declaration statement in the program scope">; def err_opencl_implicit_vector_conversion : Error< "implicit conversions between vector types (%0 and %1) are not permitted">; +def err_opencl_implicit_function_decl : Error< + "implicit declaration of function %0 is invalid in OpenCL">; +def err_opencl_dereferencing : Error< + "dereferencing pointer of type %0 is not allowed in OpenCL">; +def err_opencl_pointer_to_image : Error< + "pointer to image is invalid in OpenCL">; +def err_opencl_type_can_only_be_used_as_function_parameter : Error < + "%0 can only be used as a function parameter">; +def err_opencl_atomic_init_addressspace : Error< + "initialization of atomic variables is restricted to variables in global address space in opencl">; +def err_opencl_block_proto_variadic : Error< + "invalid block prototype, variadic arguments are not allowed in opencl">; +def err_opencl_invalid_block_array : Error< + "array of block is invalid in OpenCL">; +def err_opencl_ternary_with_block : Error< + "blocks cannot be used as expressions in ternary expressions in opencl">; // OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions def err_opencl_builtin_pipe_first_arg : Error< Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -3902,6 +3902,12 @@ // names into the program, or shall redeclare a name introduced by a // previous declaration. if (!DeclaresAnything) { + // OpenCL C doesn't support bit-field, so declaration with no declarator + // has no use. + if (getLangOpts().OpenCL) { + Diag(DS.getLocStart(), diag::err_no_declarators) << DS.getSourceRange(); + return 0; + } // In C, we allow this as a (popular) extension / bug. Don't bother // producing further diagnostics for redundant qualifiers after this. Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange(); @@ -5716,6 +5722,27 @@ QualType R = TInfo->getType(); DeclarationName Name = GetNameForDeclarator(D).getName(); + // OpenCL v2.0 s6.9.b + // An image type can only be used as a type of a function argument. + if (getLangOpts().OpenCL && R->isImageType()) { + Diag(D.getIdentifierLoc(), + diag::err_opencl_type_can_only_be_used_as_function_parameter) + << "image"; + D.setInvalidType(); + return nullptr; + } + + // OpenCL v2.0 s6.13.16.1 + // Pipes can only be passed as arguments to a function. + if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200 && + R->isPipeType()) { + Diag(D.getIdentifierLoc(), + diag::err_opencl_type_can_only_be_used_as_function_parameter) + << "pipe"; + D.setInvalidType(); + return nullptr; + } + DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec()); @@ -6704,6 +6731,24 @@ NewVD->setInvalidDecl(); return; } + + // OpenCL v2.0 s6.12.5 - The following Blocks features are currently not + // supported in OpenCL C: Blocks with variadic arguments. + if (getLangOpts().OpenCL && LangOpts.OpenCLVersion >= 200 && + T->isBlockPointerType()) { + const BlockPointerType *BlkTy = T->getAs(); + assert(BlkTy && "Not a block pointer."); + + const FunctionProtoType *FTy = + BlkTy->getPointeeType()->getAs(); + + 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 @@ -7231,8 +7276,13 @@ QualType PointeeType = PT->getPointeeType(); if (PointeeType->isPointerType()) return PtrPtrKernelParam; - return PointeeType.getAddressSpace() == 0 ? PrivatePtrKernelParam - : PtrKernelParam; + // Now generice address space is added, we need to handle like this + unsigned addrSpace = PointeeType.getAddressSpace(); + return (addrSpace != LangAS::opencl_global && + addrSpace != LangAS::opencl_constant && + addrSpace != LangAS::opencl_local) + ? PrivatePtrKernelParam + : PtrKernelParam; } // TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can @@ -7250,6 +7300,9 @@ if (PT->isHalfType()) return InvalidKernelParam; + if (PT->isReserveIDT()) + return InvalidKernelParam; + if (PT->isRecordType()) return RecordKernelParam; @@ -10712,6 +10765,15 @@ } } + // OpenCL v2.0 s6.9b2 - An image type cannot be used to declare a variable, a + // structure or union field, an array of images, a pointer to an image, or the + // return type of a function. + if (getLangOpts().OpenCL && T->isPointerType() && + T->getPointeeType()->isImageType()) { + Diag(NameLoc, diag::err_opencl_pointer_to_image); + New->setInvalidDecl(); + } + return New; } @@ -11427,6 +11489,10 @@ unsigned diag_id; if (II.getName().startswith("__builtin_")) diag_id = diag::warn_builtin_unknown; + else if (getLangOpts().OpenCL) + // OpenCL function need to be called with prototype, so we don't allow + // implicit function declarations in OpenCL + diag_id = diag::err_opencl_implicit_function_decl; else if (getLangOpts().C99) diag_id = diag::ext_implicit_function_decl; else Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -6426,6 +6426,18 @@ return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc); } +/// \brief Return true if the Expr is block type +static bool checkBlockType(Sema &S, const Expr *E) { + if (const CallExpr *CE = dyn_cast(E)) { + QualType Ty = CE->getCallee()->getType(); + if (Ty->isBlockPointerType()) { + S.Diag(E->getExprLoc(), diag::err_opencl_ternary_with_block); + return true; + } + } + return false; +} + /// Note that LHS is not null here, even if this is the gnu "x ?: y" extension. /// In that case, LHS = cond. /// C99 6.5.15 @@ -6475,6 +6487,15 @@ QualType LHSTy = LHS.get()->getType(); QualType RHSTy = RHS.get()->getType(); + // OpenCL v2.0 s6.12.5 - To support these behaviors, additional + // restrictions in addition to the above feature restrictions are: Blocks + // cannot be used as expressions of the ternary selection operator (?:). + if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200) { + // should output error for both LHS and RHS, use | instead || + if (checkBlockType(*this, LHS.get()) | checkBlockType(*this, RHS.get())) + return QualType(); + } + // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { @@ -7588,7 +7609,8 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar, QualType scalarTy, QualType vectorEltTy, - QualType vectorTy) { + QualType vectorTy, + SourceLocation Loc) { // The conversion to apply to the scalar before splatting it, // if necessary. CastKind scalarCast = CK_Invalid; @@ -7696,13 +7718,13 @@ // the vector element type and splat. if (!RHSVecType && isa(LHSVecType)) { if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, - LHSVecType->getElementType(), LHSType)) + LHSVecType->getElementType(), LHSType, Loc)) return LHSType; } if (!LHSVecType && isa(RHSVecType)) { if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), LHSType, RHSVecType->getElementType(), - RHSType)) + RHSType, Loc)) return RHSType; } @@ -10212,6 +10234,17 @@ // If the operand has type "type", the result has type "pointer to type". if (op->getType()->isObjCObjectType()) return Context.getObjCObjectPointerType(op->getType()); + + // OpenCL v2.0 s6.12.5 - The unary operators (* and &) cannot be used with a + // Block + if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200) { + if (OrigOp.get()->getType()->isBlockPointerType()) { + Diag(OpLoc, diag::err_typecheck_unary_expr) << OrigOp.get()->getType() + << op->getSourceRange(); + return QualType(); + } + } + return Context.getPointerType(op->getType()); } @@ -10253,7 +10286,17 @@ } if (const PointerType *PT = OpTy->getAs()) + { Result = PT->getPointeeType(); + // OpenCL v2.0 s6.12.5 - The unary operators (* and &) cannot be used with a + // Block. + if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion >= 200 && + Result->isBlockPointerType()) { + S.Diag(OpLoc, diag::err_opencl_dereferencing) << OpTy + << Op->getSourceRange(); + return QualType(); + } + } else if (const ObjCObjectPointerType *OPT = OpTy->getAs()) Result = OPT->getPointeeType(); Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6135,6 +6135,32 @@ << Init->getSourceRange(); } + // OpenCL v2.0 s6.13.11.1 - The ATOMIC_VAR_INIT macro expands to a token + // sequence suitable for initializing an atomic object of a type that is + // initialization-compatible with value. An atomic object with automatic + // storage duration that is not explicitly initialized using ATOMIC_VAR_INIT + // is initially in an indeterminate state; however, the default (zero) + // initialization for objects with static storage duration is guaranteed to + // produce a valid state. + // #define ATOMIC_VAR_INIT(C value) + // This macro can only be used to initialize atomic objects that are declared + // in program scope in the global address space. + // Examples: + // global atomic_int guide = ATOMIC_VAR_INIT(42); + if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion >= 200 && + Entity.getType()->isAtomicType()) { + Qualifiers TyQualifiers = Entity.getType().getQualifiers(); + bool HasGlobalAS = TyQualifiers.hasAddressSpace() && + TyQualifiers.getAddressSpace() == LangAS::opencl_global; + if (!HasGlobalAS && Entity.getKind() == InitializedEntity::EK_Variable && + Args.size() > 0) { + Expr *Init = Args[0]; + S.Diag(Init->getLocStart(), diag::err_opencl_atomic_init_addressspace) + << SourceRange(Entity.getDecl()->getLocStart(), Init->getLocEnd()); + return ExprError(); + } + } + // Diagnose cases where we initialize a pointer to an array temporary, and the // pointer obviously outlives the temporary. if (Args.size() == 1 && Args[0]->getType()->isArrayType() && Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -2175,6 +2175,14 @@ Diag(Loc, diag::warn_vla_used); } + // OpenCL v2.0 s6.12.5 - The following Blocks features are currently not + // supported in OpenCL C: Arrays of Blocks. + if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200 && + Context.getBaseElementType(T)->isBlockPointerType()) { + Diag(Loc, diag::err_opencl_invalid_block_array); + return QualType(); + } + return T; } Index: test/CodeGenOpenCL/opencl_types.cl =================================================================== --- test/CodeGenOpenCL/opencl_types.cl +++ test/CodeGenOpenCL/opencl_types.cl @@ -35,6 +35,3 @@ fnc4smp(glb_smp); // CHECK: call {{.*}}void @fnc4smp(i32 } - -void __attribute__((overloadable)) bad1(image1d_t *b, image2d_t *c, image2d_t *d) {} -// CHECK-LABEL: @{{_Z4bad1P11ocl_image1dP11ocl_image2dS2_|"\\01\?bad1@@\$\$J0YAXPE?APAUocl_image1d@@PE?APAUocl_image2d@@1@Z"}} Index: test/Parser/opencl-atomics-cl20.cl =================================================================== --- test/Parser/opencl-atomics-cl20.cl +++ test/Parser/opencl-atomics-cl20.cl @@ -56,6 +56,7 @@ #endif #ifdef CL20 +#define ATOMIC_VAR_INIT void foo(atomic_int * ptr) {} void atomic_ops_test() { atomic_int i; @@ -66,4 +67,7 @@ i += 1; // expected-error {{invalid operands to binary expression ('atomic_int' (aka '_Atomic(int)') and 'int')}} i = i + i; // expected-error {{invalid operands to binary expression ('atomic_int' (aka '_Atomic(int)') and 'atomic_int')}} } +void atomic_init_test() { + atomic_int guide = ATOMIC_VAR_INIT(42); // expected-error {{initialization of atomic variables is restricted to variables in global address space in opencl}} +} #endif Index: test/SemaOpenCL/invalid-block.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/invalid-block.cl @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify -fblocks -cl-std=CL2.0 %s + +int (^BlkVariadic)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed}} + return 0; +}; + +typedef int (^BlkInt)(int); +void f1(int i) { + BlkInt B1 = ^int(int I) {return 1;}; + BlkInt B2 = ^int(int I) {return 2;}; + BlkInt Arr[] = {B1, B2}; // expected-error {{array of block is invalid in OpenCL}} + int tmp = i ? B1(i) // expected-error {{blocks cannot be used as expressions in ternary expressions}} + : B2(i); // expected-error {{blocks cannot be used as expressions in ternary expressions}} +} + +void f2(BlkInt *BlockPtr) { + BlkInt B = ^int(int I) {return 1;}; + BlkInt *P = &B; // expected-error {{invalid argument type 'BlkInt' (aka 'int (^)(int)') to unary expression}} + B = *BlockPtr; // expected-error {{dereferencing pointer of type '__generic BlkInt *' (aka 'int (^__generic *)(int)') is not allowed}} +} + Index: test/SemaOpenCL/invalid-decl.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/invalid-decl.cl @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify -cl-std=CL2.0 %s +int; // expected-error {{declaration does not declare anything}} + +void test1(){ + myfun(); // expected-error {{implicit declaration of function 'myfun' is invalid in OpenCL}} +} Index: test/SemaOpenCL/invalid-image.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/invalid-image.cl @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -verify %s + +void test1(image1d_t *i){} // expected-error {{pointer to image is invalid in OpenCL}} + +void test2() { + image1d_t i; // expected-error {{image can only be used as a function parameter}} +} Index: test/SemaOpenCL/invalid-pipes-cl2.0.cl =================================================================== --- test/SemaOpenCL/invalid-pipes-cl2.0.cl +++ test/SemaOpenCL/invalid-pipes-cl2.0.cl @@ -6,3 +6,6 @@ } void test3(int pipe p){// expected-error {{cannot combine with previous 'int' declaration specifier}} } +void test4() { + pipe int p; // expected-error {{pipe can only be used as a function parameter}} +}